mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-28 02:57:37 +00:00
Tweaks and a test
This commit is contained in:
parent
4ce2123ecc
commit
6d0b6c0d2c
@ -52,7 +52,7 @@ pub trait GeneralizerDelegate<'tcx> {
|
||||
|
||||
fn forbid_inference_vars() -> bool;
|
||||
|
||||
fn generalize_existential(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx>;
|
||||
fn generalize_region(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx>;
|
||||
}
|
||||
|
||||
pub struct CombineDelegate<'cx, 'tcx> {
|
||||
@ -70,7 +70,9 @@ impl<'tcx> GeneralizerDelegate<'tcx> for CombineDelegate<'_, 'tcx> {
|
||||
false
|
||||
}
|
||||
|
||||
fn generalize_existential(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx> {
|
||||
fn generalize_region(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx> {
|
||||
// FIXME: This is non-ideal because we don't give a
|
||||
// very descriptive origin for this region variable.
|
||||
self.infcx
|
||||
.next_region_var_in_universe(RegionVariableOrigin::MiscVariable(self.span), universe)
|
||||
}
|
||||
@ -88,18 +90,17 @@ where
|
||||
<Self as TypeRelatingDelegate<'tcx>>::forbid_inference_vars()
|
||||
}
|
||||
|
||||
fn generalize_existential(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx> {
|
||||
fn generalize_region(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx> {
|
||||
<Self as TypeRelatingDelegate<'tcx>>::generalize_existential(self, universe)
|
||||
}
|
||||
}
|
||||
|
||||
/// The "type generalizer" is used when handling inference variables.
|
||||
/// The "generalizer" is used when handling inference variables.
|
||||
///
|
||||
/// The basic strategy for handling a constraint like `?A <: B` is to
|
||||
/// apply a "generalization strategy" to the type `B` -- this replaces
|
||||
/// all the lifetimes in the type `B` with fresh inference
|
||||
/// variables. (You can read more about the strategy in this [blog
|
||||
/// post].)
|
||||
/// apply a "generalization strategy" to the term `B` -- this replaces
|
||||
/// all the lifetimes in the term `B` with fresh inference variables.
|
||||
/// (You can read more about the strategy in this [blog post].)
|
||||
///
|
||||
/// As an example, if we had `?A <: &'x u32`, we would generalize `&'x
|
||||
/// u32` to `&'0 u32` where `'0` is a fresh variable. This becomes the
|
||||
@ -110,9 +111,11 @@ where
|
||||
struct Generalizer<'me, 'tcx, D> {
|
||||
infcx: &'me InferCtxt<'tcx>,
|
||||
|
||||
// An delegate used to abstract the behaviors of the three previous
|
||||
// generalizer-like implementations.
|
||||
pub delegate: &'me mut D,
|
||||
/// This is used to abstract the behaviors of the three previous
|
||||
/// generalizer-like implementations (`Generalizer`, `TypeGeneralizer`,
|
||||
/// and `ConstInferUnifier`). See [`GeneralizerDelegate`] for more
|
||||
/// information.
|
||||
delegate: &'me mut D,
|
||||
|
||||
/// After we generalize this type, we are going to relate it to
|
||||
/// some other type. What will be the variance at this point?
|
||||
@ -138,6 +141,7 @@ struct Generalizer<'me, 'tcx, D> {
|
||||
}
|
||||
|
||||
impl<'tcx, D> Generalizer<'_, 'tcx, D> {
|
||||
/// Create an error that corresponds to the term kind in `root_term`
|
||||
fn cyclic_term_error(&self) -> TypeError<'tcx> {
|
||||
match self.root_term.unpack() {
|
||||
ty::TermKind::Ty(ty) => TypeError::CyclicTy(ty),
|
||||
@ -183,7 +187,7 @@ where
|
||||
relate::relate_substs_with_variances(
|
||||
self,
|
||||
item_def_id,
|
||||
&opt_variances,
|
||||
opt_variances,
|
||||
a_subst,
|
||||
b_subst,
|
||||
true,
|
||||
@ -191,6 +195,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self, variance, b), ret)]
|
||||
fn relate_with_variance<T: Relate<'tcx>>(
|
||||
&mut self,
|
||||
variance: ty::Variance,
|
||||
@ -198,29 +203,21 @@ where
|
||||
a: T,
|
||||
b: T,
|
||||
) -> RelateResult<'tcx, T> {
|
||||
debug!("Generalizer::relate_with_variance(variance={:?}, a={:?}, b={:?})", variance, a, b);
|
||||
|
||||
let old_ambient_variance = self.ambient_variance;
|
||||
self.ambient_variance = self.ambient_variance.xform(variance);
|
||||
|
||||
debug!("Generalizer::relate_with_variance: ambient_variance = {:?}", self.ambient_variance);
|
||||
|
||||
debug!(?self.ambient_variance, "new ambient variance");
|
||||
let r = self.relate(a, b)?;
|
||||
|
||||
self.ambient_variance = old_ambient_variance;
|
||||
|
||||
debug!("Generalizer::relate_with_variance: r={:?}", r);
|
||||
|
||||
Ok(r)
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self, t2), ret)]
|
||||
fn tys(&mut self, t: Ty<'tcx>, t2: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
|
||||
assert_eq!(t, t2); // we are misusing TypeRelation here; both LHS and RHS ought to be ==
|
||||
|
||||
if let Some(&result) = self.cache.get(&t) {
|
||||
return Ok(result);
|
||||
}
|
||||
debug!("generalize: t={:?}", t);
|
||||
|
||||
// Check to see whether the type we are generalizing references
|
||||
// any other type variable related to `vid` via
|
||||
@ -241,21 +238,22 @@ where
|
||||
let mut inner = self.infcx.inner.borrow_mut();
|
||||
let vid = inner.type_variables().root_var(vid);
|
||||
let sub_vid = inner.type_variables().sub_root_var(vid);
|
||||
if TermVid::Ty(sub_vid) == self.root_vid {
|
||||
// If sub-roots are equal, then `for_vid` and
|
||||
|
||||
if ty::TermVid::Ty(sub_vid) == self.root_vid {
|
||||
// If sub-roots are equal, then `root_vid` and
|
||||
// `vid` are related via subtyping.
|
||||
Err(self.cyclic_term_error())
|
||||
} else {
|
||||
let probe = inner.type_variables().probe(vid);
|
||||
match probe {
|
||||
TypeVariableValue::Known { value: u } => {
|
||||
debug!("generalize: known value {:?}", u);
|
||||
drop(inner);
|
||||
self.relate(u, u)
|
||||
}
|
||||
TypeVariableValue::Unknown { universe } => {
|
||||
match self.ambient_variance {
|
||||
// Invariant: no need to make a fresh type variable.
|
||||
// Invariant: no need to make a fresh type variable
|
||||
// if we can name the universe.
|
||||
ty::Invariant => {
|
||||
if self.for_universe.can_name(universe) {
|
||||
return Ok(t);
|
||||
@ -282,7 +280,7 @@ where
|
||||
// operation. This is needed to detect cyclic types. To see why, see the
|
||||
// docs in the `type_variables` module.
|
||||
inner.type_variables().sub(vid, new_var_id);
|
||||
debug!("generalize: replacing original vid={:?} with new={:?}", vid, u);
|
||||
debug!("replacing original vid={:?} with new={:?}", vid, u);
|
||||
Ok(u)
|
||||
}
|
||||
}
|
||||
@ -297,22 +295,17 @@ where
|
||||
}
|
||||
|
||||
ty::Placeholder(placeholder) => {
|
||||
if self.for_universe.cannot_name(placeholder.universe) {
|
||||
if self.for_universe.can_name(placeholder.universe) {
|
||||
Ok(t)
|
||||
} else {
|
||||
debug!(
|
||||
"Generalizer::tys: root universe {:?} cannot name\
|
||||
placeholder in universe {:?}",
|
||||
"root universe {:?} cannot name placeholder in universe {:?}",
|
||||
self.for_universe, placeholder.universe
|
||||
);
|
||||
Err(TypeError::Mismatch)
|
||||
} else {
|
||||
Ok(t)
|
||||
}
|
||||
}
|
||||
|
||||
ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
|
||||
let s = self.relate(substs, substs)?;
|
||||
Ok(if s == substs { t } else { self.tcx().mk_opaque(def_id, s) })
|
||||
}
|
||||
_ => relate::super_relate_tys(self, t, t),
|
||||
}?;
|
||||
|
||||
@ -320,6 +313,7 @@ where
|
||||
Ok(g)
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self, r2), ret)]
|
||||
fn regions(
|
||||
&mut self,
|
||||
r: ty::Region<'tcx>,
|
||||
@ -327,8 +321,6 @@ where
|
||||
) -> RelateResult<'tcx, ty::Region<'tcx>> {
|
||||
assert_eq!(r, r2); // we are misusing TypeRelation here; both LHS and RHS ought to be ==
|
||||
|
||||
debug!("generalize: regions r={:?}", r);
|
||||
|
||||
match *r {
|
||||
// Never make variables for regions bound within the type itself,
|
||||
// nor for erased regions.
|
||||
@ -336,6 +328,8 @@ where
|
||||
return Ok(r);
|
||||
}
|
||||
|
||||
// It doesn't really matter for correctness if we generalize ReError,
|
||||
// since we're already on a doomed compilation path.
|
||||
ty::ReError(_) => {
|
||||
return Ok(r);
|
||||
}
|
||||
@ -359,13 +353,10 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: This is non-ideal because we don't give a
|
||||
// very descriptive origin for this region variable.
|
||||
let replacement_region_vid = self.delegate.generalize_existential(self.for_universe);
|
||||
|
||||
Ok(replacement_region_vid)
|
||||
Ok(self.delegate.generalize_region(self.for_universe))
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self, c2), ret)]
|
||||
fn consts(
|
||||
&mut self,
|
||||
c: ty::Const<'tcx>,
|
||||
@ -378,13 +369,12 @@ where
|
||||
bug!("unexpected inference variable encountered in NLL generalization: {:?}", c);
|
||||
}
|
||||
ty::ConstKind::Infer(InferConst::Var(vid)) => {
|
||||
// Check if the current unification would end up
|
||||
// unifying `target_vid` with a const which contains
|
||||
// an inference variable which is unioned with `target_vid`.
|
||||
//
|
||||
// Not doing so can easily result in stack overflows.
|
||||
if TermVid::Const(self.infcx.inner.borrow_mut().const_unification_table().find(vid))
|
||||
== self.root_vid
|
||||
// If root const vids are equal, then `root_vid` and
|
||||
// `vid` are related and we'd be inferring an infinitely
|
||||
// deep const.
|
||||
if ty::TermVid::Const(
|
||||
self.infcx.inner.borrow_mut().const_unification_table().find(vid),
|
||||
) == self.root_vid
|
||||
{
|
||||
return Err(self.cyclic_term_error());
|
||||
}
|
||||
@ -421,10 +411,22 @@ where
|
||||
)?;
|
||||
Ok(self.tcx().mk_const(ty::UnevaluatedConst { def, substs }, c.ty()))
|
||||
}
|
||||
ty::ConstKind::Placeholder(placeholder) => {
|
||||
if self.for_universe.can_name(placeholder.universe) {
|
||||
Ok(c)
|
||||
} else {
|
||||
debug!(
|
||||
"root universe {:?} cannot name placeholder in universe {:?}",
|
||||
self.for_universe, placeholder.universe
|
||||
);
|
||||
Err(TypeError::Mismatch)
|
||||
}
|
||||
}
|
||||
_ => relate::super_relate_consts(self, c, c),
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self), ret)]
|
||||
fn binders<T>(
|
||||
&mut self,
|
||||
a: ty::Binder<'tcx, T>,
|
||||
@ -433,7 +435,6 @@ where
|
||||
where
|
||||
T: Relate<'tcx>,
|
||||
{
|
||||
debug!("Generalizer::binders(a={:?})", a);
|
||||
let result = self.relate(a.skip_binder(), a.skip_binder())?;
|
||||
Ok(a.rebind(result))
|
||||
}
|
||||
|
18
tests/ui/traits/non_lifetime_binders/universe-error1.rs
Normal file
18
tests/ui/traits/non_lifetime_binders/universe-error1.rs
Normal file
@ -0,0 +1,18 @@
|
||||
#![feature(non_lifetime_binders)]
|
||||
//~^ WARN the feature `non_lifetime_binders` is incomplete
|
||||
|
||||
trait Other<U: ?Sized> {}
|
||||
|
||||
impl<U: ?Sized> Other<U> for U {}
|
||||
|
||||
#[rustfmt::skip]
|
||||
fn foo<U: ?Sized>()
|
||||
where
|
||||
for<T> T: Other<U> {}
|
||||
|
||||
fn bar() {
|
||||
foo::<_>();
|
||||
//~^ ERROR the trait bound `T: Other<_>` is not satisfied
|
||||
}
|
||||
|
||||
fn main() {}
|
27
tests/ui/traits/non_lifetime_binders/universe-error1.stderr
Normal file
27
tests/ui/traits/non_lifetime_binders/universe-error1.stderr
Normal file
@ -0,0 +1,27 @@
|
||||
warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/universe-error1.rs:1:12
|
||||
|
|
||||
LL | #![feature(non_lifetime_binders)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
error[E0277]: the trait bound `T: Other<_>` is not satisfied
|
||||
--> $DIR/universe-error1.rs:14:11
|
||||
|
|
||||
LL | foo::<_>();
|
||||
| ^ the trait `Other<_>` is not implemented for `T`
|
||||
|
|
||||
note: required by a bound in `foo`
|
||||
--> $DIR/universe-error1.rs:11:15
|
||||
|
|
||||
LL | fn foo<U: ?Sized>()
|
||||
| --- required by a bound in this function
|
||||
LL | where
|
||||
LL | for<T> T: Other<U> {}
|
||||
| ^^^^^^^^ required by this bound in `foo`
|
||||
|
||||
error: aborting due to previous error; 1 warning emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
Loading…
Reference in New Issue
Block a user