@@ -1991,107 +1991,197 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1991
1991
}
1992
1992
}
1993
1993
1994
+ /// We want to achieve the error span in the following example:
1995
+ ///
1996
+ /// ```
1997
+ /// struct Burrito<Filling> {
1998
+ /// filling: Filling,
1999
+ /// }
2000
+ /// impl <Filling: Delicious> Delicious for Burrito<Filling> {}
2001
+ /// fn eat_delicious_food<Food: Delicious>(food: Food) {}
2002
+ ///
2003
+ /// fn will_type_error() {
2004
+ /// eat_delicious_food(Burrito { filling: Kale });
2005
+ /// } // ^--- The trait bound `Kale: Delicious` is not satisfied
2006
+ /// ```
2007
+ ///
2008
+ /// Without calling this function, the error span will cover the entire `Burrito { ... }` expression.
2009
+ ///
2010
+ /// The strategy to determine this span involves connecting information about our generic `impl`
2011
+ /// with information about our (struct) type and the (struct) literal expression:
2012
+ /// - Find the `impl` (`impl <Filling: Delicious> Delicious for Burrito<Filling>`)
2013
+ /// that links our obligation (`Kale: Delicious`) with the parent obligation (`Burrito<Kale>: Delicious`)
2014
+ /// - Find the "original" predicate constraint in the impl (`Filling: Delicious`) which produced our obligation.
2015
+ /// - Find all of the generics that are mentioned in the predicate (`Filling`).
2016
+ /// - Examine the `Self` type in the `impl`, and see which of its type argument(s) mention any of those generics.
2017
+ /// - Examing the definition for the `Self` type, and identify (for each of its variants) if there's a unique field
2018
+ /// which uses those generic arguments.
2019
+ /// - If there is a unique field mentioning the "blameable" arguments, use that field for the error span.
2020
+ ///
2021
+ /// Before we do any of this logic, we recursively call `point_at_specific_expr_if_possible` on the parent
2022
+ /// obligation. Hence we refine the `expr` "outwards-in" and bail at the first kind of expression/impl we don't recognize.
2023
+ ///
2024
+ /// This function returns a `Result<&Expr, &Expr>` - either way, it returns the `Expr` whose span should be
2025
+ /// reported as an error. If it is `Ok`, then it means it refined successfull. If it is `Err`, then it may be
2026
+ /// only a partial success - but it cannot be refined even further.
2027
+ ///
2028
+ /// `point_at_specific_expr_if_possible` will ultimately return the returned `Expr` whether it is `Ok` or `Err`;
2029
+ /// this error state is only used for propagation within these recursive functions.
1994
2030
fn point_at_specific_expr_if_possible_for_derived_predicate_obligation (
1995
2031
& self ,
1996
2032
obligation : & traits:: ImplDerivedObligationCause < ' tcx > ,
1997
2033
expr : & ' tcx hir:: Expr < ' tcx > ,
1998
2034
) -> Result < & ' tcx hir:: Expr < ' tcx > , & ' tcx hir:: Expr < ' tcx > > {
1999
- if obligation. derived . parent_trait_pred . skip_binder ( ) . polarity != ty:: ImplPolarity :: Positive
2000
- {
2001
- // For now, ignore non-positive trait bounds.
2002
- return Err ( expr) ;
2003
- }
2004
-
2035
+ // First, we attempt to refine the `expr` for our span using the parent obligation.
2036
+ // If this cannot be done, then we are already stuck, so we stop early (hence the use
2037
+ // of the `?` try operator here).
2005
2038
let expr = self . point_at_specific_expr_if_possible_for_obligation_cause_code (
2006
2039
& * obligation. derived . parent_code ,
2007
2040
expr,
2008
2041
) ?;
2009
2042
2043
+ // These are the generic parameters used by the `impl` that produced our current obligation.
2044
+ let impl_generics: & ty:: Generics = self . tcx . generics_of ( obligation. impl_def_id ) ;
2045
+
2046
+ // This is the "trait" (meaning, the predicate "proved" by this `impl`) which provides the `Self` type we care about.
2047
+ // For the purposes of this function, we hope that it is a `struct` type, and that our current `expr` is a literal of
2048
+ // that struct type.
2049
+ let impl_trait_self_ref: Option < ty:: TraitRef < ' tcx > > =
2050
+ self . tcx . impl_trait_ref ( obligation. impl_def_id ) ;
2051
+
2052
+ let Some ( impl_trait_self_ref) = impl_trait_self_ref else {
2053
+ // It is possible that this is absent. In this case, we make no progress.
2054
+ return Err ( expr) ;
2055
+ } ;
2056
+
2057
+ // We only really care about the `Self` type itself, which we extract from the ref.
2058
+ let impl_self_ty: Ty < ' tcx > = impl_trait_self_ref. self_ty ( ) ;
2059
+
2060
+ // We can only handle Adt types for now.
2061
+ // TODO: We could support blanket impls here as well.
2062
+ // TODO: We could support tuple impls here as well.
2063
+ // TODO: We could potentially support array/vec/slice impls here as well.
2064
+ // TODO: We could support ref impls here as well.
2065
+ // Note that there is no point in supporting "primitive" types like char/i32,
2066
+ // since we cannot refine such a span any more anyway.
2067
+ let ty:: Adt ( impl_self_ty_path, impl_self_ty_args) = impl_self_ty. kind ( ) else {
2068
+ return Err ( expr) ;
2069
+ } ;
2070
+
2071
+ // We want to find which of the generics in the `impl_generics` are relevant to
2072
+ // the broken obligation predicate.
2073
+ // A generic is relevant if it is mentioned in the "original" predicate.
2074
+ // BUG: Oops, I am looking at the wrong thing here. We should find the original predicate, NOT the self type.
2075
+ // This requires adding the impl_predicate_index to the obligation when it is created. TODO: do that.
2076
+ let relevant_impl_generics: Vec < & ty:: GenericParamDef > = impl_generics
2077
+ . params
2078
+ . iter ( )
2079
+ . filter ( |param| find_param_def_in_ty_walker ( impl_self_ty. walk ( ) , param) )
2080
+ . collect ( ) ;
2081
+
2082
+ // We need to find which of the type's arguments are relevant to this obligation.
2083
+ // For example, if we had an impl for `SomeTime<(A, C), B, Result<B, C>>` and the broken obligation
2084
+ // was `B: Display` then we'd care about indexes `vec![1, 2]`, but if it was `C: PartialEq` then we'd
2085
+ // care about index `vec![0, 2]`.
2086
+ let relevant_ty_args_indices: Vec < usize > = impl_self_ty_args
2087
+ . as_slice ( )
2088
+ . iter ( )
2089
+ . enumerate ( )
2090
+ . filter ( |( _index, ty_arg) | {
2091
+ relevant_impl_generics
2092
+ . iter ( )
2093
+ . any ( |param| find_param_def_in_ty_walker ( ty_arg. walk ( ) , param) )
2094
+ } )
2095
+ . map ( |( index, _ty_arg) | index)
2096
+ . collect ( ) ;
2097
+
2098
+ eprintln ! ( "@@@@@@@@@@@@ checing expr..." ) ;
2099
+
2100
+ // Different expression require different treatment. In general, we hope that we have a literal
2101
+ // expression which produces the current `Self` type. Moreoever, we hope that it has a single
2102
+ // field which can be "blamed" for the missing trait, so that it can be highlighted.
2010
2103
match expr. kind {
2011
2104
hir:: ExprKind :: Struct (
2012
2105
hir:: QPath :: Resolved (
2013
2106
None ,
2014
- hir:: Path {
2015
- res : hir:: def:: Res :: Def ( hir:: def:: DefKind :: Struct , struct_def_id) ,
2016
- ..
2017
- } ,
2107
+ hir:: Path { res : hir:: def:: Res :: Def ( struct_def_kind, struct_def_id) , .. } ,
2018
2108
) ,
2019
2109
struct_fields,
2020
2110
_, // NOTE: "Rest" fields in structs are currently ignored by this function.
2021
2111
) => {
2022
- let impl_generics: & ty:: Generics = self . tcx . generics_of ( obligation. impl_def_id ) ;
2023
- // The relevant generics occur in this predicate.
2112
+ // We can directly support `Variant` and `Struct` struct expressions:
2113
+ let ( struct_variant_def, struct_def_generics) : ( & ty:: VariantDef , & ty:: Generics ) =
2114
+ match struct_def_kind {
2115
+ hir:: def:: DefKind :: Struct => {
2116
+ if & impl_self_ty_path. did ( ) != struct_def_id {
2117
+ // If the struct is not the same as `Self`, we cannot refine.
2118
+ return Err ( expr) ;
2119
+ }
2024
2120
2025
- // Now we look up the Self type for the trait impl.
2026
- let impl_trait_ref: Option < ty:: TraitRef < ' tcx > > =
2027
- self . tcx . impl_trait_ref ( obligation. impl_def_id ) ;
2121
+ let struct_def_generics: & ty:: Generics =
2122
+ self . tcx . generics_of ( struct_def_id) ;
2028
2123
2029
- let Some ( impl_trait_ref) = impl_trait_ref else {
2030
- return Err ( expr) ; // We must have a valid impl ref.
2031
- } ;
2032
- let impl_self_ty: Ty < ' tcx > = impl_trait_ref. self_ty ( ) ;
2124
+ let struct_variant_defs: Vec < & ty:: VariantDef > =
2125
+ impl_self_ty_path. variants ( ) . iter ( ) . collect :: < Vec < _ > > ( ) ;
2033
2126
2034
- let ty:: Adt ( impl_self_ty_path, impl_self_ty_args) = impl_self_ty. kind ( ) else {
2035
- return Err ( expr) ;
2036
- } ;
2127
+ if struct_variant_defs. len ( ) != 1 {
2128
+ // We expect exactly one variant to exist, since it's a struct type.
2129
+ return Err ( expr) ;
2130
+ }
2037
2131
2038
- if & impl_self_ty_path. did ( ) != struct_def_id {
2039
- // If the struct in the impl is different from the struct constructor
2040
- // we're using, then we cannot make progress.
2041
- return Err ( expr) ;
2042
- }
2132
+ // Use the sole variant definition as our variant from now on:
2133
+ ( struct_variant_defs[ 0 ] , struct_def_generics)
2134
+ }
2135
+ hir:: def:: DefKind :: Variant => {
2136
+ let variant_def_id = * struct_def_id;
2137
+ let struct_def_id = self . tcx . parent ( variant_def_id) ;
2043
2138
2044
- // The struct being constructed is the same as the struct in the impl.
2139
+ if impl_self_ty_path. did ( ) != struct_def_id {
2140
+ // If the struct is not the same as `Self`, we cannot refine.
2141
+ return Err ( expr) ;
2142
+ }
2045
2143
2046
- // Which of the self's type arguments use variables used in the predicate?
2047
- let mut relevant_impl_generics: Vec < & ty:: GenericParamDef > = Vec :: new ( ) ;
2048
- for param in impl_generics. params . iter ( ) {
2049
- if find_param_def_in_ty_walker ( impl_self_ty. walk ( ) , param) {
2050
- relevant_impl_generics. push ( param) ;
2051
- }
2052
- }
2053
- let mut relevant_ty_args_indices: Vec < usize > = Vec :: new ( ) ;
2054
- for ( index, ty_arg) in impl_self_ty_args. as_slice ( ) . iter ( ) . enumerate ( ) {
2055
- let mut found = false ;
2056
- for param in relevant_impl_generics. iter ( ) {
2057
- if find_param_def_in_ty_walker ( ty_arg. walk ( ) , param) {
2058
- found = true ;
2059
- }
2060
- }
2061
- if found {
2062
- relevant_ty_args_indices. push ( index) ;
2063
- }
2064
- // in ty_arg, at least one of the type parameters mentioned above must be used.
2065
- }
2144
+ let struct_def_generics: & ty:: Generics =
2145
+ self . tcx . generics_of ( struct_def_id) ;
2066
2146
2067
- let struct_def_generics: & ty:: Generics = self . tcx . generics_of ( struct_def_id) ;
2147
+ let struct_variant_def: Option < & ty:: VariantDef > = impl_self_ty_path
2148
+ . variants ( )
2149
+ . iter ( )
2150
+ . find ( |variant : & & ty:: VariantDef | variant. def_id == variant_def_id) ;
2068
2151
2069
- let struct_variant_defs: Vec < & ty:: VariantDef > =
2070
- impl_self_ty_path. variants ( ) . iter ( ) . collect :: < Vec < _ > > ( ) ;
2152
+ let Some ( struct_variant_def) = struct_variant_def else {
2153
+ // Failed to find matching variant.
2154
+ return Err ( expr) ;
2155
+ } ;
2071
2156
2072
- if struct_variant_defs. len ( ) != 1 {
2073
- // We expect exactly one variant to exist, since it's a struct type.
2074
- return Err ( expr) ;
2075
- }
2157
+ // Use the sole variant definition as our variant from now on:
2158
+ ( struct_variant_def, struct_def_generics)
2159
+ }
2160
+ _ => {
2161
+ return Err ( expr) ;
2162
+ }
2163
+ } ;
2076
2164
2077
- let struct_variant_def: & ty:: VariantDef = struct_variant_defs[ 0 ] ;
2165
+ // Only retain the generics which are relevant (according to the `impl`).
2166
+ let struct_def_generics: Vec < & ty:: GenericParamDef > = relevant_ty_args_indices
2167
+ . into_iter ( )
2168
+ . filter_map ( |index| struct_def_generics. params . get ( index) )
2169
+ . collect ( ) ;
2078
2170
2079
- let mut blameable_field_defs: Vec < & ty:: FieldDef > = Vec :: new ( ) ;
2080
- for field_def in struct_variant_def. fields . iter ( ) {
2081
- let field_type: Ty < ' tcx > = self . tcx . type_of ( field_def. did ) ;
2082
- let mut is_blameable = false ;
2171
+ // The struct being constructed is the same as the struct in the impl.
2083
2172
2084
- for param in struct_def_generics. params . iter ( ) {
2085
- if find_param_def_in_ty_walker ( field_type. walk ( ) , param) {
2086
- is_blameable = true ;
2087
- break ;
2088
- }
2089
- }
2173
+ let blameable_field_defs: Vec < & ty:: FieldDef > = struct_variant_def
2174
+ . fields
2175
+ . iter ( )
2176
+ . filter ( |field_def| {
2177
+ let field_type: Ty < ' tcx > = self . tcx . type_of ( field_def. did ) ;
2090
2178
2091
- if is_blameable {
2092
- blameable_field_defs. push ( field_def) ;
2093
- }
2094
- }
2179
+ // Only retain fields which mention the blameable generics.
2180
+ struct_def_generics
2181
+ . iter ( )
2182
+ . any ( |param| find_param_def_in_ty_walker ( field_type. walk ( ) , param) )
2183
+ } )
2184
+ . collect ( ) ;
2095
2185
2096
2186
if blameable_field_defs. len ( ) != 1 {
2097
2187
// We must have a single blameable field, in order to be able to blame it.
@@ -2110,7 +2200,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2110
2200
// We failed to find a matching field in the original struct expression.
2111
2201
Err ( expr)
2112
2202
}
2113
- _ => Err ( expr) , // Stop propagating.
2203
+ _ => {
2204
+ eprintln ! ( "!!!!!!!!!!!!! cannot handle expr {:#?}" , expr) ;
2205
+ Err ( expr)
2206
+ } // Stop propagating.
2114
2207
}
2115
2208
}
2116
2209
0 commit comments