Skip to content

Commit 4efa4a5

Browse files
committed
Implement changes suggested by varkor
1 parent 7217d76 commit 4efa4a5

File tree

4 files changed

+86
-31
lines changed

4 files changed

+86
-31
lines changed

compiler/rustc_passes/src/lang_items.rs

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,8 @@ impl LanguageItemCollector<'tcx> {
182182
}
183183
}
184184

185+
// Like collect_item() above, but also checks whether the lang item is declared
186+
// with the right number of generic arguments if it is a trait.
185187
fn collect_item_extended(&mut self, item_index: usize, hir_id: HirId, span: Span) {
186188
let item_def_id = self.tcx.hir().local_def_id(hir_id).to_def_id();
187189
let lang_item = LangItem::from_u32(item_index as u32).unwrap();
@@ -190,10 +192,15 @@ impl LanguageItemCollector<'tcx> {
190192
self.collect_item(item_index, item_def_id);
191193

192194
// Now check whether the lang_item has the expected number of generic
193-
// arguments. Binary and indexing operations have one (for the RHS/index),
194-
// unary operations have no generic arguments.
195+
// arguments if it is a trait. Generally speaking, binary and indexing
196+
// operations have one (for the RHS/index), unary operations have none,
197+
// and the rest also have none except for the closure traits (one for
198+
// the argument list), generators (one for the resume argument),
199+
// ordering/equality relations (one for the RHS), and various conversion
200+
// traits.
195201

196202
let expected_num = match lang_item {
203+
// Binary operations
197204
LangItem::Add
198205
| LangItem::Sub
199206
| LangItem::Mul
@@ -215,11 +222,48 @@ impl LanguageItemCollector<'tcx> {
215222
| LangItem::ShlAssign
216223
| LangItem::ShrAssign
217224
| LangItem::Index
218-
| LangItem::IndexMut => Some(1),
225+
| LangItem::IndexMut
219226

220-
LangItem::Neg | LangItem::Not | LangItem::Deref | LangItem::DerefMut => Some(0),
227+
// Miscellaneous
228+
| LangItem::Unsize
229+
| LangItem::CoerceUnsized
230+
| LangItem::DispatchFromDyn
231+
| LangItem::Fn
232+
| LangItem::FnMut
233+
| LangItem::FnOnce
234+
| LangItem::Generator
235+
| LangItem::PartialEq
236+
| LangItem::PartialOrd
237+
=> Some(1),
221238

222-
// FIXME: add more cases?
239+
// Unary operations
240+
LangItem::Neg
241+
| LangItem::Not
242+
243+
// Miscellaneous
244+
| LangItem::Deref
245+
| LangItem::DerefMut
246+
| LangItem::Sized
247+
| LangItem::StructuralPeq
248+
| LangItem::StructuralTeq
249+
| LangItem::Copy
250+
| LangItem::Clone
251+
| LangItem::Sync
252+
| LangItem::DiscriminantKind
253+
| LangItem::PointeeTrait
254+
| LangItem::Freeze
255+
| LangItem::Drop
256+
| LangItem::Receiver
257+
| LangItem::Future
258+
| LangItem::Unpin
259+
| LangItem::Termination
260+
| LangItem::Try
261+
| LangItem::Send
262+
| LangItem::UnwindSafe
263+
| LangItem::RefUnwindSafe
264+
=> Some(0),
265+
266+
// Not a trait
223267
_ => None,
224268
};
225269

compiler/rustc_typeck/src/check/mod.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1190,3 +1190,17 @@ fn fatally_break_rust(sess: &Session) {
11901190
fn potentially_plural_count(count: usize, word: &str) -> String {
11911191
format!("{} {}{}", count, word, pluralize!(count))
11921192
}
1193+
1194+
fn has_expected_num_generic_args<'tcx>(
1195+
tcx: TyCtxt<'tcx>,
1196+
trait_did: Option<DefId>,
1197+
mut expected: usize,
1198+
) -> bool {
1199+
trait_did.map_or(true, |trait_did| {
1200+
let generics = tcx.generics_of(trait_did);
1201+
if generics.has_self {
1202+
expected += 1;
1203+
}
1204+
generics.count() == expected
1205+
})
1206+
}

compiler/rustc_typeck/src/check/op.rs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Code related to processing overloaded binary and unary operators.
22
33
use super::method::MethodCallee;
4-
use super::FnCtxt;
4+
use super::{has_expected_num_generic_args, FnCtxt};
55
use rustc_ast as ast;
66
use rustc_errors::{self, struct_span_err, Applicability, DiagnosticBuilder};
77
use rustc_hir as hir;
@@ -800,17 +800,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
800800
// elsewhere by now, but we have to catch it here so that we do not
801801
// index `other_tys` out of bounds (if the lang item has too many
802802
// generic arguments, `other_tys` is too short).
803-
if let Some(trait_did) = trait_did {
804-
let generics = self.tcx.generics_of(trait_did);
805-
let expected_num = match op {
803+
if !has_expected_num_generic_args(
804+
self.tcx,
805+
trait_did,
806+
match op {
806807
// Binary ops have a generic right-hand side, unary ops don't
807808
Op::Binary(..) => 1,
808809
Op::Unary(..) => 0,
809-
} + if generics.has_self { 1 } else { 0 };
810-
let num_generics = generics.count();
811-
if num_generics != expected_num {
812-
return Err(());
813-
}
810+
},
811+
) {
812+
return Err(());
814813
}
815814

816815
let method = trait_did.and_then(|trait_did| {

compiler/rustc_typeck/src/check/place_op.rs

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::check::method::MethodCallee;
2-
use crate::check::{FnCtxt, PlaceOp};
2+
use crate::check::{has_expected_num_generic_args, FnCtxt, PlaceOp};
33
use rustc_hir as hir;
44
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
55
use rustc_infer::infer::InferOk;
@@ -157,16 +157,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
157157
// If the lang item was declared incorrectly, stop here so that we don't
158158
// run into an ICE (#83893). The error is reported where the lang item is
159159
// declared.
160-
if let Some(trait_did) = imm_tr {
161-
let generics = self.tcx.generics_of(trait_did);
162-
let expected_num = match op {
160+
if !has_expected_num_generic_args(
161+
self.tcx,
162+
imm_tr,
163+
match op {
163164
PlaceOp::Deref => 0,
164165
PlaceOp::Index => 1,
165-
} + if generics.has_self { 1 } else { 0 };
166-
let num_generics = generics.count();
167-
if num_generics != expected_num {
168-
return None;
169-
}
166+
},
167+
) {
168+
return None;
170169
}
171170

172171
imm_tr.and_then(|trait_did| {
@@ -197,16 +196,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
197196
// If the lang item was declared incorrectly, stop here so that we don't
198197
// run into an ICE (#83893). The error is reported where the lang item is
199198
// declared.
200-
if let Some(trait_did) = mut_tr {
201-
let generics = self.tcx.generics_of(trait_did);
202-
let expected_num = match op {
199+
if !has_expected_num_generic_args(
200+
self.tcx,
201+
mut_tr,
202+
match op {
203203
PlaceOp::Deref => 0,
204204
PlaceOp::Index => 1,
205-
} + if generics.has_self { 1 } else { 0 };
206-
let num_generics = generics.count();
207-
if num_generics != expected_num {
208-
return None;
209-
}
205+
},
206+
) {
207+
return None;
210208
}
211209

212210
mut_tr.and_then(|trait_did| {

0 commit comments

Comments
 (0)