1 use rustc_errors::ErrorGuaranteed; 2 use rustc_infer::infer::nll_relate::{TypeRelating, TypeRelatingDelegate}; 3 use rustc_infer::infer::NllRegionVariableOrigin; 4 use rustc_infer::traits::PredicateObligations; 5 use rustc_middle::mir::ConstraintCategory; 6 use rustc_middle::traits::query::NoSolution; 7 use rustc_middle::ty::relate::TypeRelation; 8 use rustc_middle::ty::{self, Ty}; 9 use rustc_span::symbol::sym; 10 use rustc_span::{Span, Symbol}; 11 12 use crate::constraints::OutlivesConstraint; 13 use crate::diagnostics::UniverseInfo; 14 use crate::renumber::{BoundRegionInfo, RegionCtxt}; 15 use crate::type_check::{InstantiateOpaqueType, Locations, TypeChecker}; 16 17 impl<'a, 'tcx> TypeChecker<'a, 'tcx> { 18 /// Adds sufficient constraints to ensure that `a R b` where `R` depends on `v`: 19 /// 20 /// - "Covariant" `a <: b` 21 /// - "Invariant" `a == b` 22 /// - "Contravariant" `a :> b` 23 /// 24 /// N.B., the type `a` is permitted to have unresolved inference 25 /// variables, but not the type `b`. 26 #[instrument(skip(self), level = "debug")] relate_types( &mut self, a: Ty<'tcx>, v: ty::Variance, b: Ty<'tcx>, locations: Locations, category: ConstraintCategory<'tcx>, ) -> Result<(), NoSolution>27 pub(super) fn relate_types( 28 &mut self, 29 a: Ty<'tcx>, 30 v: ty::Variance, 31 b: Ty<'tcx>, 32 locations: Locations, 33 category: ConstraintCategory<'tcx>, 34 ) -> Result<(), NoSolution> { 35 TypeRelating::new( 36 self.infcx, 37 NllTypeRelatingDelegate::new(self, locations, category, UniverseInfo::relate(a, b)), 38 v, 39 ) 40 .relate(a, b)?; 41 Ok(()) 42 } 43 44 /// Add sufficient constraints to ensure `a == b`. See also [Self::relate_types]. eq_substs( &mut self, a: ty::SubstsRef<'tcx>, b: ty::SubstsRef<'tcx>, locations: Locations, category: ConstraintCategory<'tcx>, ) -> Result<(), NoSolution>45 pub(super) fn eq_substs( 46 &mut self, 47 a: ty::SubstsRef<'tcx>, 48 b: ty::SubstsRef<'tcx>, 49 locations: Locations, 50 category: ConstraintCategory<'tcx>, 51 ) -> Result<(), NoSolution> { 52 TypeRelating::new( 53 self.infcx, 54 NllTypeRelatingDelegate::new(self, locations, category, UniverseInfo::other()), 55 ty::Variance::Invariant, 56 ) 57 .relate(a, b)?; 58 Ok(()) 59 } 60 } 61 62 struct NllTypeRelatingDelegate<'me, 'bccx, 'tcx> { 63 type_checker: &'me mut TypeChecker<'bccx, 'tcx>, 64 65 /// Where (and why) is this relation taking place? 66 locations: Locations, 67 68 /// What category do we assign the resulting `'a: 'b` relationships? 69 category: ConstraintCategory<'tcx>, 70 71 /// Information so that error reporting knows what types we are relating 72 /// when reporting a bound region error. 73 universe_info: UniverseInfo<'tcx>, 74 } 75 76 impl<'me, 'bccx, 'tcx> NllTypeRelatingDelegate<'me, 'bccx, 'tcx> { new( type_checker: &'me mut TypeChecker<'bccx, 'tcx>, locations: Locations, category: ConstraintCategory<'tcx>, universe_info: UniverseInfo<'tcx>, ) -> Self77 fn new( 78 type_checker: &'me mut TypeChecker<'bccx, 'tcx>, 79 locations: Locations, 80 category: ConstraintCategory<'tcx>, 81 universe_info: UniverseInfo<'tcx>, 82 ) -> Self { 83 Self { type_checker, locations, category, universe_info } 84 } 85 } 86 87 impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> { span(&self) -> Span88 fn span(&self) -> Span { 89 self.locations.span(self.type_checker.body) 90 } 91 param_env(&self) -> ty::ParamEnv<'tcx>92 fn param_env(&self) -> ty::ParamEnv<'tcx> { 93 self.type_checker.param_env 94 } 95 create_next_universe(&mut self) -> ty::UniverseIndex96 fn create_next_universe(&mut self) -> ty::UniverseIndex { 97 let universe = self.type_checker.infcx.create_next_universe(); 98 self.type_checker 99 .borrowck_context 100 .constraints 101 .universe_causes 102 .insert(universe, self.universe_info.clone()); 103 universe 104 } 105 106 #[instrument(skip(self), level = "debug")] next_existential_region_var( &mut self, from_forall: bool, _name: Option<Symbol>, ) -> ty::Region<'tcx>107 fn next_existential_region_var( 108 &mut self, 109 from_forall: bool, 110 _name: Option<Symbol>, 111 ) -> ty::Region<'tcx> { 112 let origin = NllRegionVariableOrigin::Existential { from_forall }; 113 114 let reg_var = 115 self.type_checker.infcx.next_nll_region_var(origin, || RegionCtxt::Existential(_name)); 116 117 reg_var 118 } 119 120 #[instrument(skip(self), level = "debug")] next_placeholder_region(&mut self, placeholder: ty::PlaceholderRegion) -> ty::Region<'tcx>121 fn next_placeholder_region(&mut self, placeholder: ty::PlaceholderRegion) -> ty::Region<'tcx> { 122 let reg = self 123 .type_checker 124 .borrowck_context 125 .constraints 126 .placeholder_region(self.type_checker.infcx, placeholder); 127 128 let reg_info = match placeholder.bound.kind { 129 ty::BoundRegionKind::BrAnon(Some(span)) => BoundRegionInfo::Span(span), 130 ty::BoundRegionKind::BrAnon(..) => BoundRegionInfo::Name(sym::anon), 131 ty::BoundRegionKind::BrNamed(_, name) => BoundRegionInfo::Name(name), 132 ty::BoundRegionKind::BrEnv => BoundRegionInfo::Name(sym::env), 133 }; 134 135 if cfg!(debug_assertions) { 136 let mut var_to_origin = self.type_checker.infcx.reg_var_to_origin.borrow_mut(); 137 let new = RegionCtxt::Placeholder(reg_info); 138 let prev = var_to_origin.insert(reg.as_var(), new); 139 if let Some(prev) = prev { 140 assert_eq!(new, prev); 141 } 142 } 143 144 reg 145 } 146 147 #[instrument(skip(self), level = "debug")] generalize_existential(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx>148 fn generalize_existential(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx> { 149 let reg = self.type_checker.infcx.next_nll_region_var_in_universe( 150 NllRegionVariableOrigin::Existential { from_forall: false }, 151 universe, 152 ); 153 154 if cfg!(debug_assertions) { 155 let mut var_to_origin = self.type_checker.infcx.reg_var_to_origin.borrow_mut(); 156 let prev = var_to_origin.insert(reg.as_var(), RegionCtxt::Existential(None)); 157 assert_eq!(prev, None); 158 } 159 160 reg 161 } 162 push_outlives( &mut self, sup: ty::Region<'tcx>, sub: ty::Region<'tcx>, info: ty::VarianceDiagInfo<'tcx>, )163 fn push_outlives( 164 &mut self, 165 sup: ty::Region<'tcx>, 166 sub: ty::Region<'tcx>, 167 info: ty::VarianceDiagInfo<'tcx>, 168 ) { 169 let sub = self.type_checker.borrowck_context.universal_regions.to_region_vid(sub); 170 let sup = self.type_checker.borrowck_context.universal_regions.to_region_vid(sup); 171 self.type_checker.borrowck_context.constraints.outlives_constraints.push( 172 OutlivesConstraint { 173 sup, 174 sub, 175 locations: self.locations, 176 span: self.locations.span(self.type_checker.body), 177 category: self.category, 178 variance_info: info, 179 from_closure: false, 180 }, 181 ); 182 } 183 forbid_inference_vars() -> bool184 fn forbid_inference_vars() -> bool { 185 true 186 } 187 register_obligations(&mut self, obligations: PredicateObligations<'tcx>)188 fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) { 189 let _: Result<_, ErrorGuaranteed> = self.type_checker.fully_perform_op( 190 self.locations, 191 self.category, 192 InstantiateOpaqueType { 193 obligations, 194 // These fields are filled in during execution of the operation 195 base_universe: None, 196 region_constraints: None, 197 }, 198 ); 199 } 200 } 201