Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit e54cf80

Browse files
committed
Simplify
1 parent d66a337 commit e54cf80

File tree

1 file changed

+89
-101
lines changed

1 file changed

+89
-101
lines changed

src/tools/rust-analyzer/crates/hir-ty/src/variance.rs

Lines changed: 89 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,16 @@
66
use crate::db::HirDatabase;
77
use crate::generics::{generics, Generics};
88
use crate::{
9-
AliasTy, Const, ConstScalar, DynTyExt, FnPointer, GenericArg, GenericArgData, Interner,
10-
Lifetime, LifetimeData, Ty, TyKind,
9+
AliasTy, Const, ConstScalar, DynTyExt, GenericArg, GenericArgData, Interner, Lifetime,
10+
LifetimeData, Ty, TyKind,
1111
};
1212
use base_db::ra_salsa::Cycle;
1313
use chalk_ir::Mutability;
1414
use hir_def::data::adt::StructFlags;
1515
use hir_def::{AdtId, GenericDefId, GenericParamId, VariantId};
1616
use std::fmt;
1717
use std::ops::Not;
18+
use stdx::never;
1819
use triomphe::Arc;
1920

2021
pub(crate) fn variances_of(db: &dyn HirDatabase, def: GenericDefId) -> Option<Arc<[Variance]>> {
@@ -156,9 +157,19 @@ impl Variance {
156157
(x, Variance::Bivariant) | (Variance::Bivariant, x) => x,
157158
}
158159
}
160+
161+
pub fn invariant(self) -> Self {
162+
self.xform(Variance::Invariant)
163+
}
164+
165+
pub fn covariant(self) -> Self {
166+
self.xform(Variance::Covariant)
167+
}
168+
169+
pub fn contravariant(self) -> Self {
170+
self.xform(Variance::Contravariant)
171+
}
159172
}
160-
#[derive(Copy, Clone, Debug)]
161-
struct InferredIndex(usize);
162173

163174
struct Context<'db> {
164175
db: &'db dyn HirDatabase,
@@ -193,12 +204,12 @@ impl Context<'_> {
193204
}
194205
GenericDefId::FunctionId(f) => {
195206
let subst = self.generics.placeholder_subst(self.db);
196-
self.add_constraints_from_sig2(
197-
&self
198-
.db
207+
self.add_constraints_from_sig(
208+
self.db
199209
.callable_item_signature(f.into())
200210
.substitute(Interner, &subst)
201-
.params_and_return,
211+
.params_and_return
212+
.iter(),
202213
Variance::Covariant,
203214
);
204215
}
@@ -216,41 +227,15 @@ impl Context<'_> {
216227

217228
// Functions are permitted to have unused generic parameters: make those invariant.
218229
if let GenericDefId::FunctionId(_) = self.generics.def() {
219-
for variance in &mut variances {
220-
if *variance == Variance::Bivariant {
221-
*variance = Variance::Invariant;
222-
}
223-
}
230+
variances
231+
.iter_mut()
232+
.filter(|&&mut v| v == Variance::Bivariant)
233+
.for_each(|v| *v = Variance::Invariant);
224234
}
225235

226236
variances
227237
}
228238

229-
fn contravariant(&mut self, variance: Variance) -> Variance {
230-
variance.xform(Variance::Contravariant)
231-
}
232-
233-
fn invariant(&mut self, variance: Variance) -> Variance {
234-
variance.xform(Variance::Invariant)
235-
}
236-
237-
fn add_constraints_from_invariant_args(&mut self, args: &[GenericArg], variance: Variance) {
238-
tracing::debug!(
239-
"add_constraints_from_invariant_args(args={:?}, variance={:?})",
240-
args,
241-
variance
242-
);
243-
let variance_i = self.invariant(variance);
244-
245-
for k in args {
246-
match k.data(Interner) {
247-
GenericArgData::Lifetime(lt) => self.add_constraints_from_region(lt, variance_i),
248-
GenericArgData::Ty(ty) => self.add_constraints_from_ty(ty, variance_i),
249-
GenericArgData::Const(val) => self.add_constraints_from_const(val, variance_i),
250-
}
251-
}
252-
}
253-
254239
/// Adds constraints appropriate for an instance of `ty` appearing
255240
/// in a context with the generics defined in `generics` and
256241
/// ambient variance `variance`
@@ -260,39 +245,31 @@ impl Context<'_> {
260245
TyKind::Scalar(_) | TyKind::Never | TyKind::Str | TyKind::Foreign(..) => {
261246
// leaf type -- noop
262247
}
263-
264248
TyKind::FnDef(..) | TyKind::Coroutine(..) | TyKind::Closure(..) => {
265-
panic!("Unexpected unnameable type in variance computation: {ty:?}");
249+
never!("Unexpected unnameable type in variance computation: {:?}", ty);
266250
}
267-
268251
TyKind::Ref(mutbl, lifetime, ty) => {
269252
self.add_constraints_from_region(lifetime, variance);
270253
self.add_constraints_from_mt(ty, *mutbl, variance);
271254
}
272-
273255
TyKind::Array(typ, len) => {
274256
self.add_constraints_from_const(len, variance);
275257
self.add_constraints_from_ty(typ, variance);
276258
}
277-
278259
TyKind::Slice(typ) => {
279260
self.add_constraints_from_ty(typ, variance);
280261
}
281-
282262
TyKind::Raw(mutbl, ty) => {
283263
self.add_constraints_from_mt(ty, *mutbl, variance);
284264
}
285-
286265
TyKind::Tuple(_, subtys) => {
287266
for subty in subtys.type_parameters(Interner) {
288267
self.add_constraints_from_ty(&subty, variance);
289268
}
290269
}
291-
292270
TyKind::Adt(def, args) => {
293271
self.add_constraints_from_args(def.0.into(), args.as_slice(Interner), variance);
294272
}
295-
296273
TyKind::Alias(AliasTy::Opaque(opaque)) => {
297274
self.add_constraints_from_invariant_args(
298275
opaque.substitution.as_slice(Interner),
@@ -313,7 +290,6 @@ impl Context<'_> {
313290
TyKind::OpaqueType(_, subst) => {
314291
self.add_constraints_from_invariant_args(subst.as_slice(Interner), variance);
315292
}
316-
317293
TyKind::Dyn(it) => {
318294
// The type `dyn Trait<T> +'a` is covariant w/r/t `'a`:
319295
self.add_constraints_from_region(&it.lifetime, variance);
@@ -352,20 +328,33 @@ impl Context<'_> {
352328
// Chalk has no params, so use placeholders for now?
353329
TyKind::Placeholder(index) => {
354330
let idx = crate::from_placeholder_idx(self.db, *index);
355-
let inferred = InferredIndex(self.generics.type_or_const_param_idx(idx).unwrap());
356-
self.constrain(inferred, variance);
331+
let index = self.generics.type_or_const_param_idx(idx).unwrap();
332+
self.constrain(index, variance);
357333
}
358334
TyKind::Function(f) => {
359-
self.add_constraints_from_sig(f, variance);
335+
self.add_constraints_from_sig(
336+
f.substitution.0.iter(Interner).filter_map(move |p| p.ty(Interner)),
337+
variance,
338+
);
360339
}
361-
362340
TyKind::Error => {
363341
// we encounter this when walking the trait references for object
364342
// types, where we use Error as the Self type
365343
}
366-
367344
TyKind::CoroutineWitness(..) | TyKind::BoundVar(..) | TyKind::InferenceVar(..) => {
368-
panic!("unexpected type encountered in variance inference: {:?}", ty);
345+
never!("unexpected type encountered in variance inference: {:?}", ty)
346+
}
347+
}
348+
}
349+
350+
fn add_constraints_from_invariant_args(&mut self, args: &[GenericArg], variance: Variance) {
351+
let variance_i = variance.invariant();
352+
353+
for k in args {
354+
match k.data(Interner) {
355+
GenericArgData::Lifetime(lt) => self.add_constraints_from_region(lt, variance_i),
356+
GenericArgData::Ty(ty) => self.add_constraints_from_ty(ty, variance_i),
357+
GenericArgData::Const(val) => self.add_constraints_from_const(val, variance_i),
369358
}
370359
}
371360
}
@@ -378,27 +367,19 @@ impl Context<'_> {
378367
args: &[GenericArg],
379368
variance: Variance,
380369
) {
381-
tracing::debug!(
382-
"add_constraints_from_args(def_id={:?}, args={:?}, variance={:?})",
383-
def_id,
384-
args,
385-
variance
386-
);
387-
388370
// We don't record `inferred_starts` entries for empty generics.
389371
if args.is_empty() {
390372
return;
391373
}
392374
if def_id == self.generics.def() {
393375
// HACK: Workaround for the trivial cycle salsa case (see
394376
// recursive_one_bivariant_more_non_bivariant_params test)
395-
let variance_i = variance.xform(Variance::Bivariant);
396377
for k in args {
397378
match k.data(Interner) {
398379
GenericArgData::Lifetime(lt) => {
399-
self.add_constraints_from_region(lt, variance_i)
380+
self.add_constraints_from_region(lt, Variance::Bivariant)
400381
}
401-
GenericArgData::Ty(ty) => self.add_constraints_from_ty(ty, variance_i),
382+
GenericArgData::Ty(ty) => self.add_constraints_from_ty(ty, Variance::Bivariant),
402383
GenericArgData::Const(val) => self.add_constraints_from_const(val, variance),
403384
}
404385
}
@@ -408,12 +389,13 @@ impl Context<'_> {
408389
};
409390

410391
for (i, k) in args.iter().enumerate() {
411-
let variance_i = variance.xform(variances[i]);
412392
match k.data(Interner) {
413393
GenericArgData::Lifetime(lt) => {
414-
self.add_constraints_from_region(lt, variance_i)
394+
self.add_constraints_from_region(lt, variance.xform(variances[i]))
395+
}
396+
GenericArgData::Ty(ty) => {
397+
self.add_constraints_from_ty(ty, variance.xform(variances[i]))
415398
}
416-
GenericArgData::Ty(ty) => self.add_constraints_from_ty(ty, variance_i),
417399
GenericArgData::Const(val) => self.add_constraints_from_const(val, variance),
418400
}
419401
}
@@ -435,20 +417,17 @@ impl Context<'_> {
435417

436418
/// Adds constraints appropriate for a function with signature
437419
/// `sig` appearing in a context with ambient variance `variance`
438-
fn add_constraints_from_sig(&mut self, sig: &FnPointer, variance: Variance) {
439-
let contra = self.contravariant(variance);
440-
let mut tys = sig.substitution.0.iter(Interner).filter_map(move |p| p.ty(Interner));
441-
self.add_constraints_from_ty(tys.next_back().unwrap(), variance);
442-
for input in tys {
443-
self.add_constraints_from_ty(input, contra);
444-
}
445-
}
446-
447-
fn add_constraints_from_sig2(&mut self, sig: &[Ty], variance: Variance) {
448-
let contra = self.contravariant(variance);
449-
let mut tys = sig.iter();
450-
self.add_constraints_from_ty(tys.next_back().unwrap(), variance);
451-
for input in tys {
420+
fn add_constraints_from_sig<'a>(
421+
&mut self,
422+
mut sig_tys: impl DoubleEndedIterator<Item = &'a Ty>,
423+
variance: Variance,
424+
) {
425+
let contra = variance.contravariant();
426+
let Some(output) = sig_tys.next_back() else {
427+
return never!("function signature has no return type");
428+
};
429+
self.add_constraints_from_ty(output, variance);
430+
for input in sig_tys {
452431
self.add_constraints_from_ty(input, contra);
453432
}
454433
}
@@ -462,27 +441,23 @@ impl Context<'_> {
462441
variance
463442
);
464443
match region.data(Interner) {
465-
// FIXME: chalk has no params?
466444
LifetimeData::Placeholder(index) => {
467445
let idx = crate::lt_from_placeholder_idx(self.db, *index);
468-
let inferred = InferredIndex(self.generics.lifetime_idx(idx).unwrap());
446+
let inferred = self.generics.lifetime_idx(idx).unwrap();
469447
self.constrain(inferred, variance);
470448
}
471449
LifetimeData::Static => {}
472-
473450
LifetimeData::BoundVar(..) => {
474451
// Either a higher-ranked region inside of a type or a
475452
// late-bound function parameter.
476453
//
477454
// We do not compute constraints for either of these.
478455
}
479-
480456
LifetimeData::Error => {}
481-
482457
LifetimeData::Phantom(..) | LifetimeData::InferenceVar(..) | LifetimeData::Erased => {
483458
// We don't expect to see anything but 'static or bound
484459
// regions when visiting member types or method types.
485-
panic!(
460+
never!(
486461
"unexpected region encountered in variance \
487462
inference: {:?}",
488463
region
@@ -494,26 +469,23 @@ impl Context<'_> {
494469
/// Adds constraints appropriate for a mutability-type pair
495470
/// appearing in a context with ambient variance `variance`
496471
fn add_constraints_from_mt(&mut self, ty: &Ty, mt: Mutability, variance: Variance) {
497-
match mt {
498-
Mutability::Mut => {
499-
let invar = self.invariant(variance);
500-
self.add_constraints_from_ty(ty, invar);
501-
}
502-
503-
Mutability::Not => {
504-
self.add_constraints_from_ty(ty, variance);
505-
}
506-
}
472+
self.add_constraints_from_ty(
473+
ty,
474+
match mt {
475+
Mutability::Mut => variance.invariant(),
476+
Mutability::Not => variance,
477+
},
478+
);
507479
}
508480

509-
fn constrain(&mut self, inferred: InferredIndex, variance: Variance) {
481+
fn constrain(&mut self, index: usize, variance: Variance) {
510482
tracing::debug!(
511483
"constrain(index={:?}, variance={:?}, to={:?})",
512-
inferred,
513-
self.variances[inferred.0],
484+
index,
485+
self.variances[index],
514486
variance
515487
);
516-
self.variances[inferred.0] = self.variances[inferred.0].glb(variance);
488+
self.variances[index] = self.variances[index].glb(variance);
517489
}
518490
}
519491

@@ -967,6 +939,22 @@ fn bar<'min,'max>(v: SomeStruct<&'min ()>)
967939
);
968940
}
969941

942+
#[test]
943+
fn invalid_arg_counts() {
944+
check(
945+
r#"
946+
struct S<T>(T);
947+
struct S2<T>(S<>);
948+
struct S3<T>(S<T, T>);
949+
"#,
950+
expect![[r#"
951+
S[T: covariant]
952+
S2[T: bivariant]
953+
S3[T: covariant]
954+
"#]],
955+
);
956+
}
957+
970958
#[test]
971959
fn recursive_one_bivariant_more_non_bivariant_params() {
972960
// FIXME: This is wrong, this should be `BivariantPartialIndirect[T: bivariant, U: covariant]` (likewise for Wrapper)

0 commit comments

Comments
 (0)