]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_borrowck/src/type_check/relate_tys.rs
Rollup merge of #101655 - dns2utf8:box_docs, r=dtolnay
[rust.git] / compiler / rustc_borrowck / src / type_check / relate_tys.rs
1 use rustc_infer::infer::nll_relate::{NormalizationStrategy, TypeRelating, TypeRelatingDelegate};
2 use rustc_infer::infer::NllRegionVariableOrigin;
3 use rustc_infer::traits::PredicateObligations;
4 use rustc_middle::mir::ConstraintCategory;
5 use rustc_middle::ty::error::TypeError;
6 use rustc_middle::ty::relate::TypeRelation;
7 use rustc_middle::ty::{self, Const, Ty};
8 use rustc_span::Span;
9 use rustc_trait_selection::traits::query::Fallible;
10
11 use crate::constraints::OutlivesConstraint;
12 use crate::diagnostics::UniverseInfo;
13 use crate::type_check::{InstantiateOpaqueType, Locations, TypeChecker};
14
15 impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
16     /// Adds sufficient constraints to ensure that `a R b` where `R` depends on `v`:
17     ///
18     /// - "Covariant" `a <: b`
19     /// - "Invariant" `a == b`
20     /// - "Contravariant" `a :> b`
21     ///
22     /// N.B., the type `a` is permitted to have unresolved inference
23     /// variables, but not the type `b`.
24     #[instrument(skip(self), level = "debug")]
25     pub(super) fn relate_types(
26         &mut self,
27         a: Ty<'tcx>,
28         v: ty::Variance,
29         b: Ty<'tcx>,
30         locations: Locations,
31         category: ConstraintCategory<'tcx>,
32     ) -> Fallible<()> {
33         TypeRelating::new(
34             self.infcx,
35             NllTypeRelatingDelegate::new(self, locations, category, UniverseInfo::relate(a, b)),
36             v,
37         )
38         .relate(a, b)?;
39         Ok(())
40     }
41
42     /// Add sufficient constraints to ensure `a == b`. See also [Self::relate_types].
43     pub(super) fn eq_substs(
44         &mut self,
45         a: ty::SubstsRef<'tcx>,
46         b: ty::SubstsRef<'tcx>,
47         locations: Locations,
48         category: ConstraintCategory<'tcx>,
49     ) -> Fallible<()> {
50         TypeRelating::new(
51             self.infcx,
52             NllTypeRelatingDelegate::new(self, locations, category, UniverseInfo::other()),
53             ty::Variance::Invariant,
54         )
55         .relate(a, b)?;
56         Ok(())
57     }
58 }
59
60 struct NllTypeRelatingDelegate<'me, 'bccx, 'tcx> {
61     type_checker: &'me mut TypeChecker<'bccx, 'tcx>,
62
63     /// Where (and why) is this relation taking place?
64     locations: Locations,
65
66     /// What category do we assign the resulting `'a: 'b` relationships?
67     category: ConstraintCategory<'tcx>,
68
69     /// Information so that error reporting knows what types we are relating
70     /// when reporting a bound region error.
71     universe_info: UniverseInfo<'tcx>,
72 }
73
74 impl<'me, 'bccx, 'tcx> NllTypeRelatingDelegate<'me, 'bccx, 'tcx> {
75     fn new(
76         type_checker: &'me mut TypeChecker<'bccx, 'tcx>,
77         locations: Locations,
78         category: ConstraintCategory<'tcx>,
79         universe_info: UniverseInfo<'tcx>,
80     ) -> Self {
81         Self { type_checker, locations, category, universe_info }
82     }
83 }
84
85 impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> {
86     fn span(&self) -> Span {
87         self.locations.span(self.type_checker.body)
88     }
89
90     fn param_env(&self) -> ty::ParamEnv<'tcx> {
91         self.type_checker.param_env
92     }
93
94     fn create_next_universe(&mut self) -> ty::UniverseIndex {
95         let universe = self.type_checker.infcx.create_next_universe();
96         self.type_checker
97             .borrowck_context
98             .constraints
99             .universe_causes
100             .insert(universe, self.universe_info.clone());
101         universe
102     }
103
104     fn next_existential_region_var(&mut self, from_forall: bool) -> ty::Region<'tcx> {
105         let origin = NllRegionVariableOrigin::Existential { from_forall };
106         self.type_checker.infcx.next_nll_region_var(origin)
107     }
108
109     fn next_placeholder_region(&mut self, placeholder: ty::PlaceholderRegion) -> ty::Region<'tcx> {
110         self.type_checker
111             .borrowck_context
112             .constraints
113             .placeholder_region(self.type_checker.infcx, placeholder)
114     }
115
116     fn generalize_existential(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx> {
117         self.type_checker.infcx.next_nll_region_var_in_universe(
118             NllRegionVariableOrigin::Existential { from_forall: false },
119             universe,
120         )
121     }
122
123     fn push_outlives(
124         &mut self,
125         sup: ty::Region<'tcx>,
126         sub: ty::Region<'tcx>,
127         info: ty::VarianceDiagInfo<'tcx>,
128     ) {
129         let sub = self.type_checker.borrowck_context.universal_regions.to_region_vid(sub);
130         let sup = self.type_checker.borrowck_context.universal_regions.to_region_vid(sup);
131         self.type_checker.borrowck_context.constraints.outlives_constraints.push(
132             OutlivesConstraint {
133                 sup,
134                 sub,
135                 locations: self.locations,
136                 span: self.locations.span(self.type_checker.body),
137                 category: self.category,
138                 variance_info: info,
139                 from_closure: false,
140             },
141         );
142     }
143
144     // We don't have to worry about the equality of consts during borrow checking
145     // as consts always have a static lifetime.
146     // FIXME(oli-obk): is this really true? We can at least have HKL and with
147     // inline consts we may have further lifetimes that may be unsound to treat as
148     // 'static.
149     fn const_equate(&mut self, _a: Const<'tcx>, _b: Const<'tcx>) {}
150
151     fn normalization() -> NormalizationStrategy {
152         NormalizationStrategy::Eager
153     }
154
155     fn forbid_inference_vars() -> bool {
156         true
157     }
158
159     fn register_opaque_type_obligations(
160         &mut self,
161         obligations: PredicateObligations<'tcx>,
162     ) -> Result<(), TypeError<'tcx>> {
163         self.type_checker
164             .fully_perform_op(
165                 self.locations,
166                 self.category,
167                 InstantiateOpaqueType {
168                     obligations,
169                     // These fields are filled in during execution of the operation
170                     base_universe: None,
171                     region_constraints: None,
172                 },
173             )
174             .unwrap();
175         Ok(())
176     }
177 }