@@ -1865,6 +1865,17 @@ pub enum LvaluePreference {
1865
1865
NoPreference
1866
1866
}
1867
1867
1868
+ /// Whether `autoderef` requires types to resolve.
1869
+ #[ derive( Copy , Show , PartialEq , Eq ) ]
1870
+ pub enum UnresolvedTypeAction {
1871
+ /// Produce an error and return `ty_err` whenever a type cannot
1872
+ /// be resolved (i.e. it is `ty_infer`).
1873
+ Error ,
1874
+ /// Go on without emitting any errors, and return the unresolved
1875
+ /// type. Useful for probing, e.g. in coercions.
1876
+ Ignore
1877
+ }
1878
+
1868
1879
/// Executes an autoderef loop for the type `t`. At each step, invokes `should_stop` to decide
1869
1880
/// whether to terminate the loop. Returns the final type and number of derefs that it performed.
1870
1881
///
@@ -1874,6 +1885,7 @@ pub fn autoderef<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>,
1874
1885
sp : Span ,
1875
1886
base_ty : Ty < ' tcx > ,
1876
1887
opt_expr : Option < & ast:: Expr > ,
1888
+ unresolved_type_action : UnresolvedTypeAction ,
1877
1889
mut lvalue_pref : LvaluePreference ,
1878
1890
mut should_stop : F )
1879
1891
-> ( Ty < ' tcx > , uint , Option < T > )
@@ -1886,11 +1898,22 @@ pub fn autoderef<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>,
1886
1898
1887
1899
let mut t = base_ty;
1888
1900
for autoderefs in 0 ..fcx. tcx ( ) . sess . recursion_limit . get ( ) {
1889
- let resolved_t = structurally_resolved_type ( fcx, sp, t) ;
1890
-
1891
- if ty:: type_is_error ( resolved_t) {
1892
- return ( resolved_t, autoderefs, None ) ;
1893
- }
1901
+ let resolved_t = match unresolved_type_action {
1902
+ UnresolvedTypeAction :: Error => {
1903
+ let resolved_t = structurally_resolved_type ( fcx, sp, t) ;
1904
+ if ty:: type_is_error ( resolved_t) {
1905
+ return ( resolved_t, autoderefs, None ) ;
1906
+ }
1907
+ resolved_t
1908
+ }
1909
+ UnresolvedTypeAction :: Ignore => {
1910
+ // We can continue even when the type cannot be resolved
1911
+ // (i.e. it is an inference variable) because `ty::deref`
1912
+ // and `try_overloaded_deref` both simply return `None`
1913
+ // in such a case without producing spurious errors.
1914
+ fcx. resolve_type_vars_if_possible ( t)
1915
+ }
1916
+ } ;
1894
1917
1895
1918
match should_stop ( resolved_t, autoderefs) {
1896
1919
Some ( x) => return ( resolved_t, autoderefs, Some ( x) ) ,
@@ -2011,8 +2034,13 @@ fn autoderef_for_index<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>,
2011
2034
// autoderef that normal method probing does. They could likely be
2012
2035
// consolidated.
2013
2036
2014
- let ( ty, autoderefs, final_mt) =
2015
- autoderef ( fcx, base_expr. span , base_ty, Some ( base_expr) , lvalue_pref, |adj_ty, idx| {
2037
+ let ( ty, autoderefs, final_mt) = autoderef ( fcx,
2038
+ base_expr. span ,
2039
+ base_ty,
2040
+ Some ( base_expr) ,
2041
+ UnresolvedTypeAction :: Error ,
2042
+ lvalue_pref,
2043
+ |adj_ty, idx| {
2016
2044
let autoderefref = ty:: AutoDerefRef { autoderefs : idx, autoref : None } ;
2017
2045
step ( adj_ty, autoderefref)
2018
2046
} ) ;
@@ -3053,8 +3081,13 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
3053
3081
let expr_t = structurally_resolved_type ( fcx, expr. span ,
3054
3082
fcx. expr_ty ( base) ) ;
3055
3083
// FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
3056
- let ( _, autoderefs, field_ty) =
3057
- autoderef ( fcx, expr. span , expr_t, Some ( base) , lvalue_pref, |base_t, _| {
3084
+ let ( _, autoderefs, field_ty) = autoderef ( fcx,
3085
+ expr. span ,
3086
+ expr_t,
3087
+ Some ( base) ,
3088
+ UnresolvedTypeAction :: Error ,
3089
+ lvalue_pref,
3090
+ |base_t, _| {
3058
3091
match base_t. sty {
3059
3092
ty:: ty_struct( base_id, substs) => {
3060
3093
debug ! ( "struct named {}" , ppaux:: ty_to_string( tcx, base_t) ) ;
@@ -3146,8 +3179,13 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
3146
3179
fcx. expr_ty ( base) ) ;
3147
3180
let mut tuple_like = false ;
3148
3181
// FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
3149
- let ( _, autoderefs, field_ty) =
3150
- autoderef ( fcx, expr. span , expr_t, Some ( base) , lvalue_pref, |base_t, _| {
3182
+ let ( _, autoderefs, field_ty) = autoderef ( fcx,
3183
+ expr. span ,
3184
+ expr_t,
3185
+ Some ( base) ,
3186
+ UnresolvedTypeAction :: Error ,
3187
+ lvalue_pref,
3188
+ |base_t, _| {
3151
3189
match base_t. sty {
3152
3190
ty:: ty_struct( base_id, substs) => {
3153
3191
tuple_like = ty:: is_tuple_struct ( tcx, base_id) ;
0 commit comments