From 88a559fa9fd5d0ec24e4a28c31eb53659ca493a7 Mon Sep 17 00:00:00 2001 From: lcnr Date: Sat, 17 Feb 2024 01:42:36 +0100 Subject: [PATCH] move ty var instantiation into the generalize module --- .../rustc_infer/src/infer/relate/combine.rs | 204 +----------------- .../rustc_infer/src/infer/relate/equate.rs | 13 +- .../src/infer/relate/generalize.rs | 200 ++++++++++++++++- compiler/rustc_infer/src/infer/relate/glb.rs | 5 + compiler/rustc_infer/src/infer/relate/lub.rs | 5 + compiler/rustc_infer/src/infer/relate/nll.rs | 4 + compiler/rustc_infer/src/infer/relate/sub.rs | 13 +- .../occurs-check/associated-type.next.stderr | 8 +- .../occurs-check/associated-type.old.stderr | 8 +- .../occurs-check-nested-alias.next.stderr | 4 +- 10 files changed, 243 insertions(+), 221 deletions(-) diff --git a/compiler/rustc_infer/src/infer/relate/combine.rs b/compiler/rustc_infer/src/infer/relate/combine.rs index 2e856f6a145..454de4f9785 100644 --- a/compiler/rustc_infer/src/infer/relate/combine.rs +++ b/compiler/rustc_infer/src/infer/relate/combine.rs @@ -23,19 +23,18 @@ //! this should be correctly updated. use super::equate::Equate; -use super::generalize::{self, CombineDelegate, Generalization}; use super::glb::Glb; use super::lub::Lub; use super::sub::Sub; use crate::infer::{DefineOpaqueTypes, InferCtxt, TypeTrace}; use crate::traits::{Obligation, PredicateObligations}; use rustc_middle::infer::canonical::OriginalQueryValues; -use rustc_middle::infer::unify_key::{ConstVariableValue, EffectVarValue}; +use rustc_middle::infer::unify_key::EffectVarValue; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::relate::{RelateResult, TypeRelation}; use rustc_middle::ty::{self, InferConst, ToPredicate, Ty, TyCtxt, TypeVisitableExt}; -use rustc_middle::ty::{AliasRelationDirection, TyVar}; use rustc_middle::ty::{IntType, UintType}; +use rustc_span::Span; #[derive(Clone)] pub struct CombineFields<'infcx, 'tcx> { @@ -221,11 +220,11 @@ impl<'tcx> InferCtxt<'tcx> { } (ty::ConstKind::Infer(InferConst::Var(vid)), _) => { - return self.unify_const_variable(vid, b); + return self.instantiate_const_var(vid, b); } (_, ty::ConstKind::Infer(InferConst::Var(vid))) => { - return self.unify_const_variable(vid, a); + return self.instantiate_const_var(vid, a); } (ty::ConstKind::Infer(InferConst::EffectVar(vid)), _) => { @@ -259,73 +258,6 @@ impl<'tcx> InferCtxt<'tcx> { ty::relate::structurally_relate_consts(relation, a, b) } - /// Unifies the const variable `target_vid` with the given constant. - /// - /// This also tests if the given const `ct` contains an inference variable which was previously - /// unioned with `target_vid`. If this is the case, inferring `target_vid` to `ct` - /// would result in an infinite type as we continuously replace an inference variable - /// in `ct` with `ct` itself. - /// - /// This is especially important as unevaluated consts use their parents generics. - /// They therefore often contain unused args, making these errors far more likely. - /// - /// A good example of this is the following: - /// - /// ```compile_fail,E0308 - /// #![feature(generic_const_exprs)] - /// - /// fn bind(value: [u8; N]) -> [u8; 3 + 4] { - /// todo!() - /// } - /// - /// fn main() { - /// let mut arr = Default::default(); - /// arr = bind(arr); - /// } - /// ``` - /// - /// Here `3 + 4` ends up as `ConstKind::Unevaluated` which uses the generics - /// of `fn bind` (meaning that its args contain `N`). - /// - /// `bind(arr)` now infers that the type of `arr` must be `[u8; N]`. - /// The assignment `arr = bind(arr)` now tries to equate `N` with `3 + 4`. - /// - /// As `3 + 4` contains `N` in its args, this must not succeed. - /// - /// See `tests/ui/const-generics/occurs-check/` for more examples where this is relevant. - #[instrument(level = "debug", skip(self))] - fn unify_const_variable( - &self, - target_vid: ty::ConstVid, - ct: ty::Const<'tcx>, - ) -> RelateResult<'tcx, ty::Const<'tcx>> { - let span = match self.inner.borrow_mut().const_unification_table().probe_value(target_vid) { - ConstVariableValue::Known { value } => { - bug!("instantiating a known const var: {target_vid:?} {value} {ct}") - } - ConstVariableValue::Unknown { origin, universe: _ } => origin.span, - }; - // FIXME(generic_const_exprs): Occurs check failures for unevaluated - // constants and generic expressions are not yet handled correctly. - let Generalization { value_may_be_infer: value, has_unconstrained_ty_var } = - generalize::generalize( - self, - &mut CombineDelegate { infcx: self, span }, - ct, - target_vid, - ty::Variance::Invariant, - )?; - - if has_unconstrained_ty_var { - span_bug!(span, "unconstrained ty var when generalizing `{ct:?}`"); - } - self.inner - .borrow_mut() - .const_unification_table() - .union_value(target_vid, ConstVariableValue::Known { value }); - Ok(value) - } - fn unify_integral_variable( &self, vid_is_expected: bool, @@ -387,132 +319,6 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> { Glb::new(self, a_is_expected) } - /// Here, `dir` is either `EqTo`, `SubtypeOf`, or `SupertypeOf`. - /// The idea is that we should ensure that the type `a_ty` is equal - /// to, a subtype of, or a supertype of (respectively) the type - /// to which `b_vid` is bound. - /// - /// Since `b_vid` has not yet been instantiated with a type, we - /// will first instantiate `b_vid` with a *generalized* version - /// of `a_ty`. Generalization introduces other inference - /// variables wherever subtyping could occur. - #[instrument(skip(self), level = "debug")] - pub fn instantiate( - &mut self, - a_ty: Ty<'tcx>, - ambient_variance: ty::Variance, - b_vid: ty::TyVid, - a_is_expected: bool, - ) -> RelateResult<'tcx, ()> { - // Get the actual variable that b_vid has been inferred to - debug_assert!(self.infcx.inner.borrow_mut().type_variables().probe(b_vid).is_unknown()); - - // Generalize type of `a_ty` appropriately depending on the - // direction. As an example, assume: - // - // - `a_ty == &'x ?1`, where `'x` is some free region and `?1` is an - // inference variable, - // - and `dir` == `SubtypeOf`. - // - // Then the generalized form `b_ty` would be `&'?2 ?3`, where - // `'?2` and `?3` are fresh region/type inference - // variables. (Down below, we will relate `a_ty <: b_ty`, - // adding constraints like `'x: '?2` and `?1 <: ?3`.) - let Generalization { value_may_be_infer: b_ty, has_unconstrained_ty_var } = - generalize::generalize( - self.infcx, - &mut CombineDelegate { infcx: self.infcx, span: self.trace.span() }, - a_ty, - b_vid, - ambient_variance, - )?; - - // Constrain `b_vid` to the generalized type `b_ty`. - if let &ty::Infer(TyVar(b_ty_vid)) = b_ty.kind() { - self.infcx.inner.borrow_mut().type_variables().equate(b_vid, b_ty_vid); - } else { - self.infcx.inner.borrow_mut().type_variables().instantiate(b_vid, b_ty); - } - - if has_unconstrained_ty_var { - self.obligations.push(Obligation::new( - self.tcx(), - self.trace.cause.clone(), - self.param_env, - ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed( - b_ty.into(), - ))), - )); - } - - // Finally, relate `b_ty` to `a_ty`, as described in previous comment. - // - // FIXME(#16847): This code is non-ideal because all these subtype - // relations wind up attributed to the same spans. We need - // to associate causes/spans with each of the relations in - // the stack to get this right. - if b_ty.is_ty_var() { - // This happens for cases like `::Assoc == ?0`. - // We can't instantiate `?0` here as that would result in a - // cyclic type. We instead delay the unification in case - // the alias can be normalized to something which does not - // mention `?0`. - if self.infcx.next_trait_solver() { - let (lhs, rhs, direction) = match ambient_variance { - ty::Variance::Invariant => { - (a_ty.into(), b_ty.into(), AliasRelationDirection::Equate) - } - ty::Variance::Covariant => { - (a_ty.into(), b_ty.into(), AliasRelationDirection::Subtype) - } - ty::Variance::Contravariant => { - (b_ty.into(), a_ty.into(), AliasRelationDirection::Subtype) - } - ty::Variance::Bivariant => unreachable!("bivariant generalization"), - }; - self.obligations.push(Obligation::new( - self.tcx(), - self.trace.cause.clone(), - self.param_env, - ty::PredicateKind::AliasRelate(lhs, rhs, direction), - )); - } else { - match a_ty.kind() { - &ty::Alias(ty::Projection, data) => { - // FIXME: This does not handle subtyping correctly, we could - // instead create a new inference variable for `a_ty`, emitting - // `Projection(a_ty, a_infer)` and `a_infer <: b_ty`. - self.obligations.push(Obligation::new( - self.tcx(), - self.trace.cause.clone(), - self.param_env, - ty::ProjectionPredicate { projection_ty: data, term: b_ty.into() }, - )) - } - // The old solver only accepts projection predicates for associated types. - ty::Alias(ty::Inherent | ty::Weak | ty::Opaque, _) => { - return Err(TypeError::CyclicTy(a_ty)); - } - _ => bug!("generalizated `{a_ty:?} to infer, not an alias"), - } - } - } else { - match ambient_variance { - ty::Variance::Invariant => self.equate(a_is_expected).relate(a_ty, b_ty), - ty::Variance::Covariant => self.sub(a_is_expected).relate(a_ty, b_ty), - ty::Variance::Contravariant => self.sub(a_is_expected).relate_with_variance( - ty::Contravariant, - ty::VarianceDiagInfo::default(), - a_ty, - b_ty, - ), - ty::Variance::Bivariant => unreachable!("bivariant generalization"), - }?; - } - - Ok(()) - } - pub fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) { self.obligations.extend(obligations); } @@ -525,6 +331,8 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> { } pub trait ObligationEmittingRelation<'tcx>: TypeRelation<'tcx> { + fn span(&self) -> Span; + fn param_env(&self) -> ty::ParamEnv<'tcx>; /// Register obligations that must hold in order for this relation to hold diff --git a/compiler/rustc_infer/src/infer/relate/equate.rs b/compiler/rustc_infer/src/infer/relate/equate.rs index cb62f258373..0087add4c72 100644 --- a/compiler/rustc_infer/src/infer/relate/equate.rs +++ b/compiler/rustc_infer/src/infer/relate/equate.rs @@ -8,6 +8,7 @@ use rustc_middle::ty::TyVar; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt}; use rustc_hir::def_id::DefId; +use rustc_span::Span; /// Ensures `a` is made equal to `b`. Returns `a` on success. pub struct Equate<'combine, 'infcx, 'tcx> { @@ -81,12 +82,12 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> { infcx.inner.borrow_mut().type_variables().equate(a_id, b_id); } - (&ty::Infer(TyVar(a_id)), _) => { - self.fields.instantiate(b, ty::Invariant, a_id, self.a_is_expected)?; + (&ty::Infer(TyVar(a_vid)), _) => { + infcx.instantiate_ty_var(self, self.a_is_expected, a_vid, ty::Invariant, b)?; } - (_, &ty::Infer(TyVar(b_id))) => { - self.fields.instantiate(a, ty::Invariant, b_id, self.a_is_expected)?; + (_, &ty::Infer(TyVar(b_vid))) => { + infcx.instantiate_ty_var(self, !self.a_is_expected, b_vid, ty::Invariant, a)?; } ( @@ -170,6 +171,10 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> { } impl<'tcx> ObligationEmittingRelation<'tcx> for Equate<'_, '_, 'tcx> { + fn span(&self) -> Span { + self.fields.trace.span() + } + fn param_env(&self) -> ty::ParamEnv<'tcx> { self.fields.param_env } diff --git a/compiler/rustc_infer/src/infer/relate/generalize.rs b/compiler/rustc_infer/src/infer/relate/generalize.rs index 6a96afe7083..47045058290 100644 --- a/compiler/rustc_infer/src/infer/relate/generalize.rs +++ b/compiler/rustc_infer/src/infer/relate/generalize.rs @@ -1,5 +1,8 @@ use std::mem; +use crate::infer::nll_relate::TypeRelatingDelegate; +use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind, TypeVariableValue}; +use crate::infer::{InferCtxt, ObligationEmittingRelation, RegionVariableOrigin}; use rustc_data_structures::sso::SsoHashMap; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir::def_id::DefId; @@ -7,17 +10,204 @@ use rustc_middle::infer::unify_key::ConstVariableValue; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation}; use rustc_middle::ty::visit::MaxUniverse; -use rustc_middle::ty::{self, InferConst, Term, Ty, TyCtxt, TypeVisitable, TypeVisitableExt}; +use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_middle::ty::{AliasRelationDirection, InferConst, Term, TypeVisitable, TypeVisitableExt}; use rustc_span::Span; -use crate::infer::nll_relate::TypeRelatingDelegate; -use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind, TypeVariableValue}; -use crate::infer::{InferCtxt, RegionVariableOrigin}; +impl<'tcx> InferCtxt<'tcx> { + /// The idea is that we should ensure that the type variable `target_vid` + /// is equal to, a subtype of, or a supertype of `source_ty`. + /// + /// For this, we will instantiate `target_vid` with a *generalized* version + /// of `source_ty`. Generalization introduces other inference variables wherever + /// subtyping could occur. This also does the occurs checks, detecting whether + /// instantiating `target_vid` would result in a cyclic type. We eagerly error + /// in this case. + #[instrument(skip(self, relation, target_is_expected), level = "debug")] + pub(super) fn instantiate_ty_var>( + &self, + relation: &mut R, + target_is_expected: bool, + target_vid: ty::TyVid, + ambient_variance: ty::Variance, + source_ty: Ty<'tcx>, + ) -> RelateResult<'tcx, ()> { + debug_assert!(self.inner.borrow_mut().type_variables().probe(target_vid).is_unknown()); + + // Generalize `source_ty` depending on the current variance. As an example, assume + // `?target <: &'x ?1`, where `'x` is some free region and `?1` is an inference + // variable. + // + // Then the `generalized_ty` would be `&'?2 ?3`, where `'?2` and `?3` are fresh + // region/type inference variables. + // + // We then relate `generalized_ty <: source_ty`,adding constraints like `'x: '?2` and `?1 <: ?3`. + let Generalization { value_may_be_infer: generalized_ty, has_unconstrained_ty_var } = + generalize( + self, + &mut CombineDelegate { infcx: self, span: relation.span() }, + source_ty, + target_vid, + ambient_variance, + )?; + + // Constrain `b_vid` to the generalized type `generalized_ty`. + if let &ty::Infer(ty::TyVar(generalized_vid)) = generalized_ty.kind() { + self.inner.borrow_mut().type_variables().equate(target_vid, generalized_vid); + } else { + self.inner.borrow_mut().type_variables().instantiate(target_vid, generalized_ty); + } + + // See the comment on `Generalization::has_unconstrained_ty_var`. + if has_unconstrained_ty_var { + relation.register_predicates([ty::ClauseKind::WellFormed(generalized_ty.into())]); + } + + // Finally, relate `generalized_ty` to `source_ty`, as described in previous comment. + // + // FIXME(#16847): This code is non-ideal because all these subtype + // relations wind up attributed to the same spans. We need + // to associate causes/spans with each of the relations in + // the stack to get this right. + if generalized_ty.is_ty_var() { + // This happens for cases like `::Assoc == ?0`. + // We can't instantiate `?0` here as that would result in a + // cyclic type. We instead delay the unification in case + // the alias can be normalized to something which does not + // mention `?0`. + if self.next_trait_solver() { + let (lhs, rhs, direction) = match ambient_variance { + ty::Variance::Invariant => { + (generalized_ty.into(), source_ty.into(), AliasRelationDirection::Equate) + } + ty::Variance::Covariant => { + (generalized_ty.into(), source_ty.into(), AliasRelationDirection::Subtype) + } + ty::Variance::Contravariant => { + (source_ty.into(), generalized_ty.into(), AliasRelationDirection::Subtype) + } + ty::Variance::Bivariant => unreachable!("bivariant generalization"), + }; + + relation.register_predicates([ty::PredicateKind::AliasRelate(lhs, rhs, direction)]); + } else { + match source_ty.kind() { + &ty::Alias(ty::Projection, data) => { + // FIXME: This does not handle subtyping correctly, we could + // instead create a new inference variable `?normalized_source`, emitting + // `Projection(normalized_source, ?ty_normalized)` and `?normalized_source <: generalized_ty`. + relation.register_predicates([ty::ProjectionPredicate { + projection_ty: data, + term: generalized_ty.into(), + }]); + } + // The old solver only accepts projection predicates for associated types. + ty::Alias(ty::Inherent | ty::Weak | ty::Opaque, _) => { + return Err(TypeError::CyclicTy(source_ty)); + } + _ => bug!("generalized `{source_ty:?} to infer, not an alias"), + } + } + } else { + // HACK: make sure that we `a_is_expected` continues to be + // correct when relating the generalized type with the source. + if target_is_expected == relation.a_is_expected() { + relation.relate_with_variance( + ambient_variance, + ty::VarianceDiagInfo::default(), + generalized_ty, + source_ty, + )?; + } else { + relation.relate_with_variance( + ambient_variance.xform(ty::Contravariant), + ty::VarianceDiagInfo::default(), + source_ty, + generalized_ty, + )?; + } + } + + Ok(()) + } + + /// Instantiates the const variable `target_vid` with the given constant. + /// + /// This also tests if the given const `ct` contains an inference variable which was previously + /// unioned with `target_vid`. If this is the case, inferring `target_vid` to `ct` + /// would result in an infinite type as we continuously replace an inference variable + /// in `ct` with `ct` itself. + /// + /// This is especially important as unevaluated consts use their parents generics. + /// They therefore often contain unused args, making these errors far more likely. + /// + /// A good example of this is the following: + /// + /// ```compile_fail,E0308 + /// #![feature(generic_const_exprs)] + /// + /// fn bind(value: [u8; N]) -> [u8; 3 + 4] { + /// todo!() + /// } + /// + /// fn main() { + /// let mut arr = Default::default(); + /// arr = bind(arr); + /// } + /// ``` + /// + /// Here `3 + 4` ends up as `ConstKind::Unevaluated` which uses the generics + /// of `fn bind` (meaning that its args contain `N`). + /// + /// `bind(arr)` now infers that the type of `arr` must be `[u8; N]`. + /// The assignment `arr = bind(arr)` now tries to equate `N` with `3 + 4`. + /// + /// As `3 + 4` contains `N` in its args, this must not succeed. + /// + /// See `tests/ui/const-generics/occurs-check/` for more examples where this is relevant. + #[instrument(level = "debug", skip(self))] + pub(super) fn instantiate_const_var( + &self, + target_vid: ty::ConstVid, + source_ct: ty::Const<'tcx>, + ) -> RelateResult<'tcx, ty::Const<'tcx>> { + let span = match self.inner.borrow_mut().const_unification_table().probe_value(target_vid) { + ConstVariableValue::Known { value } => { + bug!("instantiating a known const var: {target_vid:?} {value} {source_ct}") + } + ConstVariableValue::Unknown { origin, universe: _ } => origin.span, + }; + // FIXME(generic_const_exprs): Occurs check failures for unevaluated + // constants and generic expressions are not yet handled correctly. + let Generalization { value_may_be_infer: generalized_ct, has_unconstrained_ty_var } = + generalize( + self, + &mut CombineDelegate { infcx: self, span }, + source_ct, + target_vid, + ty::Variance::Invariant, + )?; + + debug_assert!(!generalized_ct.is_ct_infer()); + if has_unconstrained_ty_var { + span_bug!(span, "unconstrained ty var when generalizing `{source_ct:?}`"); + } + + self.inner + .borrow_mut() + .const_unification_table() + .union_value(target_vid, ConstVariableValue::Known { value: generalized_ct }); + + // FIXME(generic_const_exprs): We have to make sure we actually equate + // `generalized_ct` and `source_ct` here.` + Ok(generalized_ct) + } +} /// Attempts to generalize `term` for the type variable `for_vid`. /// This checks for cycles -- that is, whether the type `term` /// references `for_vid`. -pub fn generalize<'tcx, D: GeneralizerDelegate<'tcx>, T: Into> + Relate<'tcx>>( +pub(super) fn generalize<'tcx, D: GeneralizerDelegate<'tcx>, T: Into> + Relate<'tcx>>( infcx: &InferCtxt<'tcx>, delegate: &mut D, term: T, diff --git a/compiler/rustc_infer/src/infer/relate/glb.rs b/compiler/rustc_infer/src/infer/relate/glb.rs index aa89124301e..6cf51354599 100644 --- a/compiler/rustc_infer/src/infer/relate/glb.rs +++ b/compiler/rustc_infer/src/infer/relate/glb.rs @@ -2,6 +2,7 @@ use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation}; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt}; +use rustc_span::Span; use super::combine::{CombineFields, ObligationEmittingRelation}; use super::lattice::{self, LatticeDir}; @@ -134,6 +135,10 @@ impl<'combine, 'infcx, 'tcx> LatticeDir<'infcx, 'tcx> for Glb<'combine, 'infcx, } impl<'tcx> ObligationEmittingRelation<'tcx> for Glb<'_, '_, 'tcx> { + fn span(&self) -> Span { + self.fields.trace.span() + } + fn param_env(&self) -> ty::ParamEnv<'tcx> { self.fields.param_env } diff --git a/compiler/rustc_infer/src/infer/relate/lub.rs b/compiler/rustc_infer/src/infer/relate/lub.rs index 87d777530c8..5b4f80fd73a 100644 --- a/compiler/rustc_infer/src/infer/relate/lub.rs +++ b/compiler/rustc_infer/src/infer/relate/lub.rs @@ -7,6 +7,7 @@ use crate::traits::{ObligationCause, PredicateObligations}; use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation}; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt}; +use rustc_span::Span; /// "Least upper bound" (common supertype) pub struct Lub<'combine, 'infcx, 'tcx> { @@ -134,6 +135,10 @@ impl<'combine, 'infcx, 'tcx> LatticeDir<'infcx, 'tcx> for Lub<'combine, 'infcx, } impl<'tcx> ObligationEmittingRelation<'tcx> for Lub<'_, '_, 'tcx> { + fn span(&self) -> Span { + self.fields.trace.span() + } + fn param_env(&self) -> ty::ParamEnv<'tcx> { self.fields.param_env } diff --git a/compiler/rustc_infer/src/infer/relate/nll.rs b/compiler/rustc_infer/src/infer/relate/nll.rs index fac597c9432..04995f1a117 100644 --- a/compiler/rustc_infer/src/infer/relate/nll.rs +++ b/compiler/rustc_infer/src/infer/relate/nll.rs @@ -670,6 +670,10 @@ impl<'tcx, D> ObligationEmittingRelation<'tcx> for TypeRelating<'_, 'tcx, D> where D: TypeRelatingDelegate<'tcx>, { + fn span(&self) -> Span { + self.delegate.span() + } + fn param_env(&self) -> ty::ParamEnv<'tcx> { self.delegate.param_env() } diff --git a/compiler/rustc_infer/src/infer/relate/sub.rs b/compiler/rustc_infer/src/infer/relate/sub.rs index 36876acd7c0..5bd3a238a67 100644 --- a/compiler/rustc_infer/src/infer/relate/sub.rs +++ b/compiler/rustc_infer/src/infer/relate/sub.rs @@ -6,6 +6,7 @@ use rustc_middle::ty::relate::{Cause, Relate, RelateResult, TypeRelation}; use rustc_middle::ty::visit::TypeVisitableExt; use rustc_middle::ty::TyVar; use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_span::Span; use std::mem; /// Ensures `a` is made a subtype of `b`. Returns `a` on success. @@ -103,12 +104,12 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> { Ok(a) } - (&ty::Infer(TyVar(a_id)), _) => { - self.fields.instantiate(b, ty::Contravariant, a_id, !self.a_is_expected)?; + (&ty::Infer(TyVar(a_vid)), _) => { + infcx.instantiate_ty_var(self, self.a_is_expected, a_vid, ty::Covariant, b)?; Ok(a) } - (_, &ty::Infer(TyVar(b_id))) => { - self.fields.instantiate(a, ty::Covariant, b_id, self.a_is_expected)?; + (_, &ty::Infer(TyVar(b_vid))) => { + infcx.instantiate_ty_var(self, !self.a_is_expected, b_vid, ty::Contravariant, a)?; Ok(a) } @@ -199,6 +200,10 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> { } impl<'tcx> ObligationEmittingRelation<'tcx> for Sub<'_, '_, 'tcx> { + fn span(&self) -> Span { + self.fields.trace.span() + } + fn param_env(&self) -> ty::ParamEnv<'tcx> { self.fields.param_env } diff --git a/tests/ui/coherence/occurs-check/associated-type.next.stderr b/tests/ui/coherence/occurs-check/associated-type.next.stderr index 65be4a9c884..e405f389f5e 100644 --- a/tests/ui/coherence/occurs-check/associated-type.next.stderr +++ b/tests/ui/coherence/occurs-check/associated-type.next.stderr @@ -1,11 +1,11 @@ WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }) -WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, RePlaceholder(!2_BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }) +WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, RePlaceholder(!1_BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }) WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }) -WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, RePlaceholder(!2_BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }) +WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, RePlaceholder(!1_BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }) WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }) -WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, RePlaceholder(!2_BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }) +WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, RePlaceholder(!1_BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }) WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }) -WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, RePlaceholder(!2_BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }) +WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, RePlaceholder(!1_BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }) error[E0119]: conflicting implementations of trait `Overlap fn(&'a (), ())>` for type `for<'a> fn(&'a (), ())` --> $DIR/associated-type.rs:31:1 | diff --git a/tests/ui/coherence/occurs-check/associated-type.old.stderr b/tests/ui/coherence/occurs-check/associated-type.old.stderr index 8e852ec796e..4a67a777f10 100644 --- a/tests/ui/coherence/occurs-check/associated-type.old.stderr +++ b/tests/ui/coherence/occurs-check/associated-type.old.stderr @@ -1,11 +1,11 @@ WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }) -WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, RePlaceholder(!3_BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }) +WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, RePlaceholder(!2_BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }) WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }) -WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, RePlaceholder(!3_BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }) +WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, RePlaceholder(!2_BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }) WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }) -WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, RePlaceholder(!3_BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }) +WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, RePlaceholder(!2_BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }) WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }) -WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, RePlaceholder(!3_BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }) +WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, RePlaceholder(!2_BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }) error[E0119]: conflicting implementations of trait `Overlap fn(&'a (), _)>` for type `for<'a> fn(&'a (), _)` --> $DIR/associated-type.rs:31:1 | diff --git a/tests/ui/traits/next-solver/generalize/occurs-check-nested-alias.next.stderr b/tests/ui/traits/next-solver/generalize/occurs-check-nested-alias.next.stderr index aaadf604a80..cde925db184 100644 --- a/tests/ui/traits/next-solver/generalize/occurs-check-nested-alias.next.stderr +++ b/tests/ui/traits/next-solver/generalize/occurs-check-nested-alias.next.stderr @@ -1,8 +1,8 @@ -error[E0284]: type annotations needed: cannot satisfy `<>::Id as Unnormalizable>::Assoc == _` +error[E0284]: type annotations needed: cannot satisfy `_ == <>::Id as Unnormalizable>::Assoc` --> $DIR/occurs-check-nested-alias.rs:36:9 | LL | x = y; - | ^ cannot satisfy `<>::Id as Unnormalizable>::Assoc == _` + | ^ cannot satisfy `_ == <>::Id as Unnormalizable>::Assoc` error: aborting due to 1 previous error