• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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