@@ -7,8 +7,9 @@ use chalk_ir::{
77    cast:: Cast , 
88    interner:: HasInterner , 
99    visit:: { visitors:: FindAny ,  SuperVisit ,  Visit ,  VisitResult ,  Visitor } , 
10-     ApplicationTy ,  Binders ,  DebruijnIndex ,  DomainGoal ,  DynTy ,  EqGoal ,  Goal ,  QuantifiedWhereClauses , 
11-     Substitution ,  TraitId ,  Ty ,  TyData ,  TypeName ,  WhereClause , 
10+     ApplicationTy ,  Binders ,  Const ,  ConstValue ,  DebruijnIndex ,  DomainGoal ,  DynTy ,  EqGoal ,  Goal , 
11+     LifetimeOutlives ,  QuantifiedWhereClauses ,  Substitution ,  TraitId ,  Ty ,  TyData ,  TypeName , 
12+     WhereClause , 
1213} ; 
1314
1415struct  UnsizeParameterCollector < ' a ,  I :  Interner >  { 
@@ -24,14 +25,12 @@ impl<'a, I: Interner> Visitor<'a, I> for UnsizeParameterCollector<'a, I> {
2425        self 
2526    } 
2627
27-     // FIXME(areredify) when const generics land, collect const variables too 
28- 
2928    fn  visit_ty ( & mut  self ,  ty :  & Ty < I > ,  outer_binder :  DebruijnIndex )  -> Self :: Result  { 
3029        let  interner = self . interner ; 
3130
3231        match  ty. data ( interner)  { 
3332            TyData :: BoundVar ( bound_var)  => { 
34-                 // check if bound var referse  to the outermost binder 
33+                 // check if bound var refers  to the outermost binder 
3534                if  bound_var. debruijn . shifted_in ( )  == outer_binder { 
3635                    self . parameters . insert ( bound_var. index ) ; 
3736                } 
@@ -40,6 +39,20 @@ impl<'a, I: Interner> Visitor<'a, I> for UnsizeParameterCollector<'a, I> {
4039        } 
4140    } 
4241
42+     fn  visit_const ( & mut  self ,  constant :  & Const < I > ,  outer_binder :  DebruijnIndex )  -> Self :: Result  { 
43+         let  interner = self . interner ; 
44+ 
45+         match  constant. data ( interner) . value  { 
46+             ConstValue :: BoundVar ( bound_var)  => { 
47+                 // check if bound var refers to the outermost binder 
48+                 if  bound_var. debruijn . shifted_in ( )  == outer_binder { 
49+                     self . parameters . insert ( bound_var. index ) ; 
50+                 } 
51+             } 
52+             _ => ( ) , 
53+         } 
54+     } 
55+ 
4356    fn  interner ( & self )  -> & ' a  I  { 
4457        self . interner 
4558    } 
@@ -110,36 +123,25 @@ fn principal_id<'a, I: Interner>(
110123)  -> Option < TraitId < I > >  { 
111124    let  interner = db. interner ( ) ; 
112125
113-     let  principal_id =  bounds
126+     return  bounds
114127        . skip_binders ( ) 
115128        . iter ( interner) 
116-         . next ( ) 
117-         . expect ( "Expected trait object to have at least one trait bound" ) 
118-         . trait_id ( ) ?; 
119- 
120-     if  db. trait_datum ( principal_id) . is_auto_trait ( )  { 
121-         None 
122-     }  else  { 
123-         Some ( principal_id) 
124-     } 
129+         . filter_map ( |b| b. trait_id ( ) ) 
130+         . filter ( |& id| !db. trait_datum ( id) . is_auto_trait ( ) ) 
131+         . next ( ) ; 
125132} 
126133
127134fn  auto_trait_ids < ' a ,  I :  Interner > ( 
128-     db :  & dyn  RustIrDatabase < I > , 
135+     db :  & ' a   dyn  RustIrDatabase < I > , 
129136    bounds :  & ' a  Binders < QuantifiedWhereClauses < I > > , 
130137)  -> impl  Iterator < Item  = TraitId < I > >  + ' a  { 
131138    let  interner = db. interner ( ) ; 
132-     // all trait ref where clauses after the principal are auto traits 
133-     let  to_skip = if  principal_id ( db,  bounds) . is_some ( )  { 
134-         1 
135-     }  else  { 
136-         0 
137-     } ; 
139+ 
138140    bounds
139141        . skip_binders ( ) 
140142        . iter ( interner) 
141-         . skip ( to_skip) 
142143        . filter_map ( |clause| clause. trait_id ( ) ) 
144+         . filter ( move  |& id| db. trait_datum ( id) . is_auto_trait ( ) ) 
143145} 
144146
145147pub  fn  add_unsize_program_clauses < I :  Interner > ( 
@@ -196,10 +198,11 @@ pub fn add_unsize_program_clauses<I: Interner>(
196198            } 
197199
198200            // COMMENT FROM RUSTC: 
201+             // ------------------ 
199202            // Require that the traits involved in this upcast are **equal**; 
200203            // only the **lifetime bound** is changed. 
201204            // 
202-             // FIXME:  This condition is arguably too strong -- it would 
205+             // This condition is arguably too strong -- it would 
203206            // suffice for the source trait to be a *subtype* of the target 
204207            // trait. In particular, changing from something like 
205208            // `for<'a, 'b> Foo<'a, 'b>` to `for<'a> Foo<'a, 'a>` should be 
@@ -211,11 +214,13 @@ pub fn add_unsize_program_clauses<I: Interner>(
211214            // with what our behavior should be there. -nikomatsakis 
212215            // ------------------ 
213216
214-             // Filter out auto traits of source that are not present in target 
215-             // and change source lifetime to target lifetime 
217+             // Construct a new trait object type by taking the source ty, 
218+             // filtering out auto traits of source that are not present in target 
219+             // and changing source lifetime to target lifetime. 
216220            // 
217-             // This new type should be equal to target type. 
218-             let  source_ty = TyData :: Dyn ( DynTy  { 
221+             // In order for the coercion to be valid, this new type 
222+             // should be equal to target type. 
223+             let  new_source_ty = TyData :: Dyn ( DynTy  { 
219224                bounds :  bounds_a. map_ref ( |bounds| { 
220225                    QuantifiedWhereClauses :: from ( 
221226                        interner, 
@@ -238,16 +243,15 @@ pub fn add_unsize_program_clauses<I: Interner>(
238243
239244            // Check that new source is equal to target 
240245            let  eq_goal = EqGoal  { 
241-                 a :  source_ty . cast ( interner) , 
246+                 a :  new_source_ty . cast ( interner) , 
242247                b :  target_ty. clone ( ) . cast ( interner) , 
243248            } 
244249            . cast ( interner) ; 
245250
246-             // FIXME(areredify) change this to outlives once #419 lands 
247-             let  lifetime_outlives_goal = EqGoal  { 
248-                 a :  lifetime_a. clone ( ) . cast ( interner) , 
249-                 b :  lifetime_b. clone ( ) . cast ( interner) , 
250-             } 
251+             let  lifetime_outlives_goal:  Goal < I >  = WhereClause :: LifetimeOutlives ( LifetimeOutlives  { 
252+                 a :  lifetime_a. clone ( ) , 
253+                 b :  lifetime_b. clone ( ) , 
254+             } ) 
251255            . cast ( interner) ; 
252256
253257            builder. push_clause ( trait_ref. clone ( ) ,  [ eq_goal,  lifetime_outlives_goal] . iter ( ) ) ; 
@@ -294,6 +298,27 @@ pub fn add_unsize_program_clauses<I: Interner>(
294298            ) ; 
295299        } 
296300
301+         ( 
302+             TyData :: Apply ( ApplicationTy  { 
303+                 name :  TypeName :: Array , 
304+                 substitution :  array_subst, 
305+             } ) , 
306+             TyData :: Apply ( ApplicationTy  { 
307+                 name :  TypeName :: Slice , 
308+                 substitution :  slice_subst, 
309+             } ) , 
310+         )  => { 
311+             let  array_ty = array_subst. at ( interner,  0 ) ; 
312+             let  slice_ty = slice_subst. at ( interner,  0 ) ; 
313+ 
314+             let  eq_goal = EqGoal  { 
315+                 a :  array_ty. clone ( ) , 
316+                 b :  slice_ty. clone ( ) , 
317+             } ; 
318+ 
319+             builder. push_clause ( trait_ref. clone ( ) ,  iter:: once ( eq_goal) ) ; 
320+         } 
321+ 
297322        // Struct<T> -> Struct<U> 
298323        // Unsizing of enums is not allowed 
299324        ( 
@@ -318,19 +343,18 @@ pub fn add_unsize_program_clauses<I: Interner>(
318343                return ; 
319344            } 
320345
321-             let  struct_tail_field  = struct_datum
346+             let  adt_tail_field  = struct_datum
322347                . binders 
323348                . map_ref ( |bound| bound. fields . last ( ) . unwrap ( ) ) ; 
324349
325350            // Collect unsize parameters that last field contains and 
326351            // ensure there at least one of them. 
327352            let  unsize_parameter_candidates =
328-                 outer_binder_parameters_used ( interner,  & struct_tail_field ) ; 
353+                 outer_binder_parameters_used ( interner,  & adt_tail_field ) ; 
329354
330355            if  unsize_parameter_candidates. len ( )  == 0  { 
331356                return ; 
332357            } 
333- 
334358            // Ensure none of the other fields mention the parameters used 
335359            // in unsizing. 
336360            if  uses_outer_binder_params ( 
@@ -345,15 +369,15 @@ pub fn add_unsize_program_clauses<I: Interner>(
345369
346370            let  parameters_a = substitution_a. parameters ( interner) ; 
347371            let  parameters_b = substitution_b. parameters ( interner) ; 
348-             // Check that the source struct  with the target's 
372+             // Check that the source adt  with the target's 
349373            // unsizing parameters is equal to the target. 
350374            let  substitution = Substitution :: from ( 
351375                interner, 
352376                parameters_a. iter ( ) . enumerate ( ) . map ( |( i,  p) | { 
353377                    if  unsize_parameter_candidates. contains ( & i)  { 
354-                         p
355-                     }  else  { 
356378                        & parameters_b[ i] 
379+                     }  else  { 
380+                         p
357381                    } 
358382                } ) , 
359383            ) ; 
@@ -370,8 +394,8 @@ pub fn add_unsize_program_clauses<I: Interner>(
370394            . cast ( interner) ; 
371395
372396            // Extract `TailField<T>` and `TailField<U>` from `Struct<T>` and `Struct<U>`. 
373-             let  source_tail_field = struct_tail_field . substitute ( interner,  substitution_a) ; 
374-             let  target_tail_field = struct_tail_field . substitute ( interner,  substitution_b) ; 
397+             let  source_tail_field = adt_tail_field . substitute ( interner,  substitution_a) ; 
398+             let  target_tail_field = adt_tail_field . substitute ( interner,  substitution_b) ; 
375399
376400            // Check that `TailField<T>: Unsize<TailField<U>>` 
377401            let  last_field_unsizing_goal:  Goal < I >  = TraitRef  { 
0 commit comments