Skip to content

Commit 5c54004

Browse files
committed
use instantiate_ty_var in nll
we already use `instantiate_const_var`. This does lose some debugging info for nll because we stop populating the `reg_var_to_origin` table with `RegionCtxt::Existential(None)`, I don't think that matters however. Supporting this adds additional complexity to one of the most involved parts of the type system, so I really don't think it's worth it.
1 parent 88a559f commit 5c54004

File tree

6 files changed

+48
-222
lines changed

6 files changed

+48
-222
lines changed

compiler/rustc_borrowck/src/type_check/relate_tys.rs

-16
Original file line numberDiff line numberDiff line change
@@ -143,22 +143,6 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx>
143143
reg
144144
}
145145

146-
#[instrument(skip(self), level = "debug")]
147-
fn generalize_existential(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx> {
148-
let reg = self.type_checker.infcx.next_nll_region_var_in_universe(
149-
NllRegionVariableOrigin::Existential { from_forall: false },
150-
universe,
151-
);
152-
153-
if cfg!(debug_assertions) {
154-
let mut var_to_origin = self.type_checker.infcx.reg_var_to_origin.borrow_mut();
155-
let prev = var_to_origin.insert(reg.as_var(), RegionCtxt::Existential(None));
156-
assert_eq!(prev, None);
157-
}
158-
159-
reg
160-
}
161-
162146
fn push_outlives(
163147
&mut self,
164148
sup: ty::Region<'tcx>,

compiler/rustc_infer/src/infer/canonical/query_response.rs

-7
Original file line numberDiff line numberDiff line change
@@ -731,13 +731,6 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for QueryTypeRelatingDelegate<'_, 'tcx> {
731731
ty::Region::new_placeholder(self.infcx.tcx, placeholder)
732732
}
733733

734-
fn generalize_existential(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx> {
735-
self.infcx.next_nll_region_var_in_universe(
736-
NllRegionVariableOrigin::Existential { from_forall: false },
737-
universe,
738-
)
739-
}
740-
741734
fn push_outlives(
742735
&mut self,
743736
sup: ty::Region<'tcx>,

compiler/rustc_infer/src/infer/relate/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
44
pub(super) mod combine;
55
mod equate;
6-
pub(super) mod generalize;
6+
mod generalize;
77
mod glb;
88
mod higher_ranked;
99
mod lattice;

compiler/rustc_infer/src/infer/relate/nll.rs

+46-184
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,11 @@ use rustc_data_structures::fx::FxHashMap;
2525
use rustc_middle::traits::ObligationCause;
2626
use rustc_middle::ty::fold::FnMutDelegate;
2727
use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
28-
use rustc_middle::ty::visit::TypeVisitableExt;
28+
use rustc_middle::ty::TypeVisitableExt;
2929
use rustc_middle::ty::{self, InferConst, Ty, TyCtxt};
3030
use rustc_span::{Span, Symbol};
31-
use std::fmt::Debug;
3231

3332
use super::combine::ObligationEmittingRelation;
34-
use super::generalize::{self, Generalization};
3533
use crate::infer::InferCtxt;
3634
use crate::infer::{TypeVariableOrigin, TypeVariableOriginKind};
3735
use crate::traits::{Obligation, PredicateObligations};
@@ -99,15 +97,6 @@ pub trait TypeRelatingDelegate<'tcx> {
9997
/// placeholder region.
10098
fn next_placeholder_region(&mut self, placeholder: ty::PlaceholderRegion) -> ty::Region<'tcx>;
10199

102-
/// Creates a new existential region in the given universe. This
103-
/// is used when handling subtyping and type variables -- if we
104-
/// have that `?X <: Foo<'a>`, for example, we would instantiate
105-
/// `?X` with a type like `Foo<'?0>` where `'?0` is a fresh
106-
/// existential variable created by this function. We would then
107-
/// relate `Foo<'?0>` with `Foo<'a>` (and probably add an outlives
108-
/// relation stating that `'?0: 'a`).
109-
fn generalize_existential(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx>;
110-
111100
/// Enables some optimizations if we do not expect inference variables
112101
/// in the RHS of the relation.
113102
fn forbid_inference_vars() -> bool;
@@ -153,113 +142,44 @@ where
153142
self.delegate.push_outlives(sup, sub, info);
154143
}
155144

156-
/// Relate a type inference variable with a value type. This works
157-
/// by creating a "generalization" G of the value where all the
158-
/// lifetimes are replaced with fresh inference values. This
159-
/// generalization G becomes the value of the inference variable,
160-
/// and is then related in turn to the value. So e.g. if you had
161-
/// `vid = ?0` and `value = &'a u32`, we might first instantiate
162-
/// `?0` to a type like `&'0 u32` where `'0` is a fresh variable,
163-
/// and then relate `&'0 u32` with `&'a u32` (resulting in
164-
/// relations between `'0` and `'a`).
165-
///
166-
/// The variable `pair` can be either a `(vid, ty)` or `(ty, vid)`
167-
/// -- in other words, it is always an (unresolved) inference
168-
/// variable `vid` and a type `ty` that are being related, but the
169-
/// vid may appear either as the "a" type or the "b" type,
170-
/// depending on where it appears in the tuple. The trait
171-
/// `VidValuePair` lets us work with the vid/type while preserving
172-
/// the "sidedness" when necessary -- the sidedness is relevant in
173-
/// particular for the variance and set of in-scope things.
174-
fn relate_ty_var<PAIR: VidValuePair<'tcx>>(
175-
&mut self,
176-
pair: PAIR,
177-
) -> RelateResult<'tcx, Ty<'tcx>> {
178-
debug!("relate_ty_var({:?})", pair);
179-
180-
let vid = pair.vid();
181-
let value_ty = pair.value_ty();
182-
183-
// FIXME(invariance) -- this logic assumes invariance, but that is wrong.
184-
// This only presently applies to chalk integration, as NLL
185-
// doesn't permit type variables to appear on both sides (and
186-
// doesn't use lazy norm).
187-
match *value_ty.kind() {
188-
ty::Infer(ty::TyVar(value_vid)) => {
189-
// Two type variables: just equate them.
190-
self.infcx.inner.borrow_mut().type_variables().equate(vid, value_vid);
191-
return Ok(value_ty);
192-
}
193-
194-
_ => (),
195-
}
196-
197-
let generalized_ty = self.generalize(value_ty, vid)?;
198-
debug!("relate_ty_var: generalized_ty = {:?}", generalized_ty);
199-
200-
if D::forbid_inference_vars() {
201-
// In NLL, we don't have type inference variables
202-
// floating around, so we can do this rather imprecise
203-
// variant of the occurs-check.
204-
assert!(!generalized_ty.has_non_region_infer());
205-
}
206-
207-
self.infcx.inner.borrow_mut().type_variables().instantiate(vid, generalized_ty);
208-
209-
// Relate the generalized kind to the original one.
210-
let result = pair.relate_generalized_ty(self, generalized_ty);
211-
212-
debug!("relate_ty_var: complete, result = {:?}", result);
213-
result
214-
}
215-
216-
fn generalize(&mut self, ty: Ty<'tcx>, for_vid: ty::TyVid) -> RelateResult<'tcx, Ty<'tcx>> {
217-
let Generalization { value_may_be_infer: ty, has_unconstrained_ty_var: _ } =
218-
generalize::generalize(
219-
self.infcx,
220-
&mut self.delegate,
221-
ty,
222-
for_vid,
223-
self.ambient_variance,
224-
)?;
225-
226-
if ty.is_ty_var() {
227-
span_bug!(self.delegate.span(), "occurs check failure in MIR typeck");
228-
}
229-
Ok(ty)
230-
}
231-
232-
fn relate_opaques(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
145+
fn relate_opaques(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()> {
146+
let infcx = self.infcx;
147+
debug_assert!(!infcx.next_trait_solver());
233148
let (a, b) = if self.a_is_expected() { (a, b) } else { (b, a) };
234-
let mut generalize = |ty, ty_is_expected| {
235-
let var = self.infcx.next_ty_var_id_in_universe(
149+
// `handle_opaque_type` cannot handle subtyping, so to support subtyping
150+
// we instead eagerly generalize here. This is a bit of a mess but will go
151+
// away once we're using the new solver.
152+
let mut enable_subtyping = |ty, ty_is_expected| {
153+
let ty_vid = infcx.next_ty_var_id_in_universe(
236154
TypeVariableOrigin {
237155
kind: TypeVariableOriginKind::MiscVariable,
238156
span: self.delegate.span(),
239157
},
240158
ty::UniverseIndex::ROOT,
241159
);
242-
if ty_is_expected {
243-
self.relate_ty_var((ty, var))
160+
161+
let variance = if ty_is_expected {
162+
self.ambient_variance
244163
} else {
245-
self.relate_ty_var((var, ty))
246-
}
164+
self.ambient_variance.xform(ty::Contravariant)
165+
};
166+
167+
self.infcx.instantiate_ty_var(self, ty_is_expected, ty_vid, variance, ty)?;
168+
Ok(infcx.resolve_vars_if_possible(Ty::new_infer(infcx.tcx, ty::TyVar(ty_vid))))
247169
};
170+
248171
let (a, b) = match (a.kind(), b.kind()) {
249-
(&ty::Alias(ty::Opaque, ..), _) => (a, generalize(b, false)?),
250-
(_, &ty::Alias(ty::Opaque, ..)) => (generalize(a, true)?, b),
172+
(&ty::Alias(ty::Opaque, ..), _) => (a, enable_subtyping(b, false)?),
173+
(_, &ty::Alias(ty::Opaque, ..)) => (enable_subtyping(a, true)?, b),
251174
_ => unreachable!(
252175
"expected at least one opaque type in `relate_opaques`, got {a} and {b}."
253176
),
254177
};
255178
let cause = ObligationCause::dummy_with_span(self.delegate.span());
256-
let obligations = self
257-
.infcx
258-
.handle_opaque_type(a, b, true, &cause, self.delegate.param_env())?
259-
.obligations;
179+
let obligations =
180+
infcx.handle_opaque_type(a, b, true, &cause, self.delegate.param_env())?.obligations;
260181
self.delegate.register_obligations(obligations);
261-
trace!(a = ?a.kind(), b = ?b.kind(), "opaque type instantiated");
262-
Ok(a)
182+
Ok(())
263183
}
264184

265185
fn enter_forall<T, U>(
@@ -357,76 +277,6 @@ where
357277
}
358278
}
359279

360-
/// When we instantiate an inference variable with a value in
361-
/// `relate_ty_var`, we always have the pair of a `TyVid` and a `Ty`,
362-
/// but the ordering may vary (depending on whether the inference
363-
/// variable was found on the `a` or `b` sides). Therefore, this trait
364-
/// allows us to factor out common code, while preserving the order
365-
/// when needed.
366-
trait VidValuePair<'tcx>: Debug {
367-
/// Extract the inference variable (which could be either the
368-
/// first or second part of the tuple).
369-
fn vid(&self) -> ty::TyVid;
370-
371-
/// Extract the value it is being related to (which will be the
372-
/// opposite part of the tuple from the vid).
373-
fn value_ty(&self) -> Ty<'tcx>;
374-
375-
/// Given a generalized type G that should replace the vid, relate
376-
/// G to the value, putting G on whichever side the vid would have
377-
/// appeared.
378-
fn relate_generalized_ty<D>(
379-
&self,
380-
relate: &mut TypeRelating<'_, 'tcx, D>,
381-
generalized_ty: Ty<'tcx>,
382-
) -> RelateResult<'tcx, Ty<'tcx>>
383-
where
384-
D: TypeRelatingDelegate<'tcx>;
385-
}
386-
387-
impl<'tcx> VidValuePair<'tcx> for (ty::TyVid, Ty<'tcx>) {
388-
fn vid(&self) -> ty::TyVid {
389-
self.0
390-
}
391-
392-
fn value_ty(&self) -> Ty<'tcx> {
393-
self.1
394-
}
395-
396-
fn relate_generalized_ty<D>(
397-
&self,
398-
relate: &mut TypeRelating<'_, 'tcx, D>,
399-
generalized_ty: Ty<'tcx>,
400-
) -> RelateResult<'tcx, Ty<'tcx>>
401-
where
402-
D: TypeRelatingDelegate<'tcx>,
403-
{
404-
relate.relate(generalized_ty, self.value_ty())
405-
}
406-
}
407-
408-
// In this case, the "vid" is the "b" type.
409-
impl<'tcx> VidValuePair<'tcx> for (Ty<'tcx>, ty::TyVid) {
410-
fn vid(&self) -> ty::TyVid {
411-
self.1
412-
}
413-
414-
fn value_ty(&self) -> Ty<'tcx> {
415-
self.0
416-
}
417-
418-
fn relate_generalized_ty<D>(
419-
&self,
420-
relate: &mut TypeRelating<'_, 'tcx, D>,
421-
generalized_ty: Ty<'tcx>,
422-
) -> RelateResult<'tcx, Ty<'tcx>>
423-
where
424-
D: TypeRelatingDelegate<'tcx>,
425-
{
426-
relate.relate(self.value_ty(), generalized_ty)
427-
}
428-
}
429-
430280
impl<'tcx, D> TypeRelation<'tcx> for TypeRelating<'_, 'tcx, D>
431281
where
432282
D: TypeRelatingDelegate<'tcx>,
@@ -473,29 +323,39 @@ where
473323

474324
if !D::forbid_inference_vars() {
475325
b = self.infcx.shallow_resolve(b);
326+
} else {
327+
assert!(!b.has_non_region_infer(), "unexpected inference var {:?}", b);
476328
}
477329

478330
if a == b {
479331
return Ok(a);
480332
}
481333

482334
match (a.kind(), b.kind()) {
483-
(_, &ty::Infer(ty::TyVar(vid))) => {
484-
if D::forbid_inference_vars() {
485-
// Forbid inference variables in the RHS.
486-
bug!("unexpected inference var {:?}", b)
487-
} else {
488-
self.relate_ty_var((a, vid))
335+
(&ty::Infer(ty::TyVar(a_vid)), &ty::Infer(ty::TyVar(b_vid))) => {
336+
match self.ambient_variance {
337+
ty::Invariant => infcx.inner.borrow_mut().type_variables().equate(a_vid, b_vid),
338+
_ => unimplemented!(),
489339
}
490340
}
491341

492-
(&ty::Infer(ty::TyVar(vid)), _) => self.relate_ty_var((vid, b)),
342+
(&ty::Infer(ty::TyVar(a_vid)), _) => {
343+
infcx.instantiate_ty_var(self, true, a_vid, self.ambient_variance, b)?
344+
}
345+
346+
(_, &ty::Infer(ty::TyVar(b_vid))) => infcx.instantiate_ty_var(
347+
self,
348+
false,
349+
b_vid,
350+
self.ambient_variance.xform(ty::Contravariant),
351+
a,
352+
)?,
493353

494354
(
495355
&ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, .. }),
496356
&ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }),
497357
) if a_def_id == b_def_id || infcx.next_trait_solver() => {
498-
infcx.super_combine_tys(self, a, b).or_else(|err| {
358+
infcx.super_combine_tys(self, a, b).map(|_| ()).or_else(|err| {
499359
// This behavior is only there for the old solver, the new solver
500360
// shouldn't ever fail. Instead, it unconditionally emits an
501361
// alias-relate goal.
@@ -505,22 +365,24 @@ where
505365
"failure to relate an opaque to itself should result in an error later on",
506366
);
507367
if a_def_id.is_local() { self.relate_opaques(a, b) } else { Err(err) }
508-
})
368+
})?;
509369
}
510370
(&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _)
511371
| (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }))
512372
if def_id.is_local() && !self.infcx.next_trait_solver() =>
513373
{
514-
self.relate_opaques(a, b)
374+
self.relate_opaques(a, b)?;
515375
}
516376

517377
_ => {
518378
debug!(?a, ?b, ?self.ambient_variance);
519379

520380
// Will also handle unification of `IntVar` and `FloatVar`.
521-
self.infcx.super_combine_tys(self, a, b)
381+
self.infcx.super_combine_tys(self, a, b)?;
522382
}
523383
}
384+
385+
Ok(a)
524386
}
525387

526388
#[instrument(skip(self), level = "trace")]

tests/ui/impl-trait/rpit/early_bound.rs

-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ fn test<'a: 'a>(n: bool) -> impl Sized + 'a {
55
let true = n else { loop {} };
66
let _ = || {
77
let _ = identity::<&'a ()>(test(false));
8-
//~^ ERROR hidden type for `impl Sized + 'a` captures lifetime that does not appear in bounds
98
};
109
loop {}
1110
}
+1-13
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,3 @@
1-
error[E0700]: hidden type for `impl Sized + 'a` captures lifetime that does not appear in bounds
2-
--> $DIR/early_bound.rs:7:17
3-
|
4-
LL | fn test<'a: 'a>(n: bool) -> impl Sized + 'a {
5-
| -- --------------- opaque type defined here
6-
| |
7-
| hidden type `&'a ()` captures the lifetime `'a` as defined here
8-
...
9-
LL | let _ = identity::<&'a ()>(test(false));
10-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
11-
121
error: concrete type differs from previous defining opaque type use
132
--> $DIR/early_bound.rs:3:29
143
|
@@ -21,6 +10,5 @@ note: previous use here
2110
LL | let _ = identity::<&'a ()>(test(false));
2211
| ^^^^^^^^^^^
2312

24-
error: aborting due to 2 previous errors
13+
error: aborting due to 1 previous error
2514

26-
For more information about this error, try `rustc --explain E0700`.

0 commit comments

Comments
 (0)