@@ -72,6 +72,7 @@ mod compare_method;
7272pub mod demand;
7373mod diverges;
7474pub mod dropck;
75+ mod expectation;
7576mod expr;
7677mod fn_ctxt;
7778mod gather_locals;
@@ -88,6 +89,7 @@ mod wfcheck;
8889pub mod writeback;
8990
9091pub use diverges:: Diverges ;
92+ pub use expectation:: Expectation ;
9193pub use fn_ctxt:: FnCtxt ;
9294pub use inherited:: { Inherited , InheritedBuilder } ;
9395
@@ -153,117 +155,6 @@ pub struct LocalTy<'tcx> {
153155 revealed_ty : Ty < ' tcx > ,
154156}
155157
156- /// When type-checking an expression, we propagate downward
157- /// whatever type hint we are able in the form of an `Expectation`.
158- #[ derive( Copy , Clone , Debug ) ]
159- pub enum Expectation < ' tcx > {
160- /// We know nothing about what type this expression should have.
161- NoExpectation ,
162-
163- /// This expression should have the type given (or some subtype).
164- ExpectHasType ( Ty < ' tcx > ) ,
165-
166- /// This expression will be cast to the `Ty`.
167- ExpectCastableToType ( Ty < ' tcx > ) ,
168-
169- /// This rvalue expression will be wrapped in `&` or `Box` and coerced
170- /// to `&Ty` or `Box<Ty>`, respectively. `Ty` is `[A]` or `Trait`.
171- ExpectRvalueLikeUnsized ( Ty < ' tcx > ) ,
172- }
173-
174- impl < ' a , ' tcx > Expectation < ' tcx > {
175- // Disregard "castable to" expectations because they
176- // can lead us astray. Consider for example `if cond
177- // {22} else {c} as u8` -- if we propagate the
178- // "castable to u8" constraint to 22, it will pick the
179- // type 22u8, which is overly constrained (c might not
180- // be a u8). In effect, the problem is that the
181- // "castable to" expectation is not the tightest thing
182- // we can say, so we want to drop it in this case.
183- // The tightest thing we can say is "must unify with
184- // else branch". Note that in the case of a "has type"
185- // constraint, this limitation does not hold.
186-
187- // If the expected type is just a type variable, then don't use
188- // an expected type. Otherwise, we might write parts of the type
189- // when checking the 'then' block which are incompatible with the
190- // 'else' branch.
191- fn adjust_for_branches ( & self , fcx : & FnCtxt < ' a , ' tcx > ) -> Expectation < ' tcx > {
192- match * self {
193- ExpectHasType ( ety) => {
194- let ety = fcx. shallow_resolve ( ety) ;
195- if !ety. is_ty_var ( ) { ExpectHasType ( ety) } else { NoExpectation }
196- }
197- ExpectRvalueLikeUnsized ( ety) => ExpectRvalueLikeUnsized ( ety) ,
198- _ => NoExpectation ,
199- }
200- }
201-
202- /// Provides an expectation for an rvalue expression given an *optional*
203- /// hint, which is not required for type safety (the resulting type might
204- /// be checked higher up, as is the case with `&expr` and `box expr`), but
205- /// is useful in determining the concrete type.
206- ///
207- /// The primary use case is where the expected type is a fat pointer,
208- /// like `&[isize]`. For example, consider the following statement:
209- ///
210- /// let x: &[isize] = &[1, 2, 3];
211- ///
212- /// In this case, the expected type for the `&[1, 2, 3]` expression is
213- /// `&[isize]`. If however we were to say that `[1, 2, 3]` has the
214- /// expectation `ExpectHasType([isize])`, that would be too strong --
215- /// `[1, 2, 3]` does not have the type `[isize]` but rather `[isize; 3]`.
216- /// It is only the `&[1, 2, 3]` expression as a whole that can be coerced
217- /// to the type `&[isize]`. Therefore, we propagate this more limited hint,
218- /// which still is useful, because it informs integer literals and the like.
219- /// See the test case `test/ui/coerce-expect-unsized.rs` and #20169
220- /// for examples of where this comes up,.
221- fn rvalue_hint ( fcx : & FnCtxt < ' a , ' tcx > , ty : Ty < ' tcx > ) -> Expectation < ' tcx > {
222- match fcx. tcx . struct_tail_without_normalization ( ty) . kind ( ) {
223- ty:: Slice ( _) | ty:: Str | ty:: Dynamic ( ..) => ExpectRvalueLikeUnsized ( ty) ,
224- _ => ExpectHasType ( ty) ,
225- }
226- }
227-
228- // Resolves `expected` by a single level if it is a variable. If
229- // there is no expected type or resolution is not possible (e.g.,
230- // no constraints yet present), just returns `None`.
231- fn resolve ( self , fcx : & FnCtxt < ' a , ' tcx > ) -> Expectation < ' tcx > {
232- match self {
233- NoExpectation => NoExpectation ,
234- ExpectCastableToType ( t) => ExpectCastableToType ( fcx. resolve_vars_if_possible ( & t) ) ,
235- ExpectHasType ( t) => ExpectHasType ( fcx. resolve_vars_if_possible ( & t) ) ,
236- ExpectRvalueLikeUnsized ( t) => ExpectRvalueLikeUnsized ( fcx. resolve_vars_if_possible ( & t) ) ,
237- }
238- }
239-
240- fn to_option ( self , fcx : & FnCtxt < ' a , ' tcx > ) -> Option < Ty < ' tcx > > {
241- match self . resolve ( fcx) {
242- NoExpectation => None ,
243- ExpectCastableToType ( ty) | ExpectHasType ( ty) | ExpectRvalueLikeUnsized ( ty) => Some ( ty) ,
244- }
245- }
246-
247- /// It sometimes happens that we want to turn an expectation into
248- /// a **hard constraint** (i.e., something that must be satisfied
249- /// for the program to type-check). `only_has_type` will return
250- /// such a constraint, if it exists.
251- fn only_has_type ( self , fcx : & FnCtxt < ' a , ' tcx > ) -> Option < Ty < ' tcx > > {
252- match self . resolve ( fcx) {
253- ExpectHasType ( ty) => Some ( ty) ,
254- NoExpectation | ExpectCastableToType ( _) | ExpectRvalueLikeUnsized ( _) => None ,
255- }
256- }
257-
258- /// Like `only_has_type`, but instead of returning `None` if no
259- /// hard constraint exists, creates a fresh type variable.
260- fn coercion_target_type ( self , fcx : & FnCtxt < ' a , ' tcx > , span : Span ) -> Ty < ' tcx > {
261- self . only_has_type ( fcx) . unwrap_or_else ( || {
262- fcx. next_ty_var ( TypeVariableOrigin { kind : TypeVariableOriginKind :: MiscVariable , span } )
263- } )
264- }
265- }
266-
267158#[ derive( Copy , Clone , Debug , PartialEq , Eq ) ]
268159pub enum Needs {
269160 MutPlace ,
0 commit comments