@@ -1991,107 +1991,197 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
19911991 }
19921992 }
19931993
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.
19942030 fn point_at_specific_expr_if_possible_for_derived_predicate_obligation (
19952031 & self ,
19962032 obligation : & traits:: ImplDerivedObligationCause < ' tcx > ,
19972033 expr : & ' tcx hir:: Expr < ' tcx > ,
19982034 ) -> 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).
20052038 let expr = self . point_at_specific_expr_if_possible_for_obligation_cause_code (
20062039 & * obligation. derived . parent_code ,
20072040 expr,
20082041 ) ?;
20092042
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.
20102103 match expr. kind {
20112104 hir:: ExprKind :: Struct (
20122105 hir:: QPath :: Resolved (
20132106 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) , .. } ,
20182108 ) ,
20192109 struct_fields,
20202110 _, // NOTE: "Rest" fields in structs are currently ignored by this function.
20212111 ) => {
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+ }
20242120
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) ;
20282123
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 < _ > > ( ) ;
20332126
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+ }
20372131
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) ;
20432138
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+ }
20452143
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) ;
20662146
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) ;
20682151
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+ } ;
20712156
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+ } ;
20762164
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 ( ) ;
20782170
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.
20832172
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 ) ;
20902178
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 ( ) ;
20952185
20962186 if blameable_field_defs. len ( ) != 1 {
20972187 // 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> {
21102200 // We failed to find a matching field in the original struct expression.
21112201 Err ( expr)
21122202 }
2113- _ => Err ( expr) , // Stop propagating.
2203+ _ => {
2204+ eprintln ! ( "!!!!!!!!!!!!! cannot handle expr {:#?}" , expr) ;
2205+ Err ( expr)
2206+ } // Stop propagating.
21142207 }
21152208 }
21162209
0 commit comments