@@ -24,8 +24,10 @@ use rustc_infer::infer::error_reporting::{FailureCode, ObligationCauseExt};
24
24
use rustc_infer:: infer:: type_variable:: { TypeVariableOrigin , TypeVariableOriginKind } ;
25
25
use rustc_infer:: infer:: InferOk ;
26
26
use rustc_infer:: infer:: TypeTrace ;
27
+ use rustc_infer:: traits:: PredicateObligation ;
27
28
use rustc_middle:: ty:: adjustment:: AllowTwoPhase ;
28
29
use rustc_middle:: ty:: visit:: TypeVisitable ;
30
+ use rustc_middle:: ty:: walk:: TypeWalker ;
29
31
use rustc_middle:: ty:: { self , DefIdTree , IsSuggestable , Ty , TypeSuperVisitable , TypeVisitor } ;
30
32
use rustc_session:: Session ;
31
33
use rustc_span:: symbol:: { kw, Ident } ;
@@ -523,7 +525,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
523
525
// Sometimes macros mess up the spans, so do not normalize the
524
526
// arg span to equal the error span, because that's less useful
525
527
// than pointing out the arg expr in the wrong context.
526
- if normalized_span. source_equal ( error_span) { span } else { normalized_span }
528
+ if normalized_span. source_equal ( error_span) {
529
+ span
530
+ } else {
531
+ normalized_span
532
+ }
527
533
} ;
528
534
529
535
// Precompute the provided types and spans, since that's all we typically need for below
@@ -776,9 +782,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
776
782
// can be collated pretty easily if needed.
777
783
778
784
// Next special case: if there is only one "Incompatible" error, just emit that
779
- if let [
780
- Error :: Invalid ( provided_idx, expected_idx, Compatibility :: Incompatible ( Some ( err) ) ) ,
781
- ] = & errors[ ..]
785
+ if let [ Error :: Invalid ( provided_idx, expected_idx, Compatibility :: Incompatible ( Some ( err) ) ) ] =
786
+ & errors[ ..]
782
787
{
783
788
let ( formal_ty, expected_ty) = formal_and_expected_inputs[ * expected_idx] ;
784
789
let ( provided_ty, provided_arg_span) = provided_arg_tys[ * provided_idx] ;
@@ -1520,25 +1525,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1520
1525
// Our block must be a `assign desugar local; assignment`
1521
1526
if let Some ( hir:: Node :: Block ( hir:: Block {
1522
1527
stmts :
1523
- [
1524
- hir:: Stmt {
1525
- kind :
1526
- hir:: StmtKind :: Local ( hir:: Local {
1527
- source :
1528
- hir:: LocalSource :: AssignDesugar ( _) ,
1529
- ..
1530
- } ) ,
1531
- ..
1532
- } ,
1533
- hir:: Stmt {
1534
- kind :
1535
- hir:: StmtKind :: Expr ( hir:: Expr {
1536
- kind : hir:: ExprKind :: Assign ( ..) ,
1537
- ..
1538
- } ) ,
1539
- ..
1540
- } ,
1541
- ] ,
1528
+ [ hir:: Stmt {
1529
+ kind :
1530
+ hir:: StmtKind :: Local ( hir:: Local {
1531
+ source : hir:: LocalSource :: AssignDesugar ( _) ,
1532
+ ..
1533
+ } ) ,
1534
+ ..
1535
+ } , hir:: Stmt {
1536
+ kind :
1537
+ hir:: StmtKind :: Expr ( hir:: Expr {
1538
+ kind : hir:: ExprKind :: Assign ( ..) ,
1539
+ ..
1540
+ } ) ,
1541
+ ..
1542
+ } ] ,
1542
1543
..
1543
1544
} ) ) = self . tcx . hir ( ) . find ( blk. hir_id )
1544
1545
{
@@ -1946,7 +1947,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1946
1947
if let [ ( idx, _) ] = args_referencing_param. as_slice ( )
1947
1948
&& let Some ( arg) = receiver
1948
1949
. map_or ( args. get ( * idx) , |rcvr| if * idx == 0 { Some ( rcvr) } else { args. get ( * idx - 1 ) } ) {
1950
+
1949
1951
error. obligation . cause . span = arg. span . find_ancestor_in_same_ctxt ( error. obligation . cause . span ) . unwrap_or ( arg. span ) ;
1952
+
1953
+ if let hir:: Node :: Expr ( arg_expr) = self . tcx . hir ( ) . get ( arg. hir_id ) {
1954
+ // This is more specific than pointing at the entire argument.
1955
+ self . point_at_specific_expr_if_possible ( error, arg_expr)
1956
+ }
1957
+
1950
1958
error. obligation . cause . map_code ( |parent_code| {
1951
1959
ObligationCauseCode :: FunctionArgumentObligation {
1952
1960
arg_hir_id : arg. hir_id ,
@@ -1964,6 +1972,183 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1964
1972
false
1965
1973
}
1966
1974
1975
+ fn point_at_specific_expr_if_possible_for_obligation_cause_code (
1976
+ & self ,
1977
+ obligation_cause_code : & traits:: ObligationCauseCode < ' tcx > ,
1978
+ expr : & ' tcx hir:: Expr < ' tcx > ,
1979
+ ) -> Result < & ' tcx hir:: Expr < ' tcx > , & ' tcx hir:: Expr < ' tcx > > {
1980
+ match obligation_cause_code {
1981
+ traits:: ObligationCauseCode :: ImplDerivedObligation ( impl_derived) => self
1982
+ . point_at_specific_expr_if_possible_for_derived_predicate_obligation (
1983
+ impl_derived,
1984
+ expr,
1985
+ ) ,
1986
+ traits:: ObligationCauseCode :: ExprBindingObligation ( _, _, _, _) => Ok ( expr) ,
1987
+ _ => {
1988
+ // Err(expr) indicates that we cannot process any further.
1989
+ Err ( expr)
1990
+ }
1991
+ }
1992
+ }
1993
+
1994
+ fn point_at_specific_expr_if_possible_for_derived_predicate_obligation (
1995
+ & self ,
1996
+ obligation : & traits:: ImplDerivedObligationCause < ' tcx > ,
1997
+ expr : & ' tcx hir:: Expr < ' tcx > ,
1998
+ ) -> 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
+
2005
+ let expr = self . point_at_specific_expr_if_possible_for_obligation_cause_code (
2006
+ & * obligation. derived . parent_code ,
2007
+ expr,
2008
+ ) ?;
2009
+
2010
+ match expr. kind {
2011
+ hir:: ExprKind :: Struct (
2012
+ hir:: QPath :: Resolved (
2013
+ None ,
2014
+ hir:: Path {
2015
+ res : hir:: def:: Res :: Def ( hir:: def:: DefKind :: Struct , struct_def_id) ,
2016
+ ..
2017
+ } ,
2018
+ ) ,
2019
+ struct_fields,
2020
+ _, // NOTE: "Rest" fields in structs are currently ignored by this function.
2021
+ ) => {
2022
+ let impl_generics: & ty:: Generics = self . tcx . generics_of ( obligation. impl_def_id ) ;
2023
+ // The relevant generics occur in this predicate.
2024
+
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 ) ;
2028
+
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 ( ) ;
2033
+
2034
+ let ty:: Adt ( impl_self_ty_path, impl_self_ty_args) = impl_self_ty. kind ( ) else {
2035
+ return Err ( expr) ;
2036
+ } ;
2037
+
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
+ }
2043
+
2044
+ // The struct being constructed is the same as the struct in the impl.
2045
+
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
+ }
2066
+
2067
+ let struct_def_generics: & ty:: Generics = self . tcx . generics_of ( struct_def_id) ;
2068
+
2069
+ let struct_variant_defs: Vec < & ty:: VariantDef > =
2070
+ impl_self_ty_path. variants ( ) . iter ( ) . collect :: < Vec < _ > > ( ) ;
2071
+
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
+ }
2076
+
2077
+ let struct_variant_def: & ty:: VariantDef = struct_variant_defs[ 0 ] ;
2078
+
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 ;
2083
+
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
+ }
2090
+
2091
+ if is_blameable {
2092
+ blameable_field_defs. push ( field_def) ;
2093
+ }
2094
+ }
2095
+
2096
+ if blameable_field_defs. len ( ) != 1 {
2097
+ // We must have a single blameable field, in order to be able to blame it.
2098
+ return Err ( expr) ;
2099
+ }
2100
+
2101
+ let blameable_field_def: & ty:: FieldDef = blameable_field_defs[ 0 ] ;
2102
+
2103
+ for field in struct_fields. iter ( ) {
2104
+ if field. ident . as_str ( ) == blameable_field_def. ident ( self . tcx ) . as_str ( ) {
2105
+ // Blame this field!
2106
+ return Ok ( field. expr ) ;
2107
+ }
2108
+ }
2109
+
2110
+ // We failed to find a matching field in the original struct expression.
2111
+ Err ( expr)
2112
+ }
2113
+ _ => Err ( expr) , // Stop propagating.
2114
+ }
2115
+ }
2116
+
2117
+ fn point_at_specific_expr_if_possible_for_predicate_obligation (
2118
+ & self ,
2119
+ obligation : & PredicateObligation < ' tcx > ,
2120
+ expr : & ' tcx hir:: Expr < ' tcx > ,
2121
+ ) -> Result < & ' tcx hir:: Expr < ' tcx > , & ' tcx hir:: Expr < ' tcx > > {
2122
+ self . point_at_specific_expr_if_possible_for_obligation_cause_code (
2123
+ obligation. cause . code ( ) ,
2124
+ expr,
2125
+ )
2126
+ }
2127
+
2128
+ /**
2129
+ * Recursively searches for the most-specific blamable expression.
2130
+ * Specifically, looks for constructor expressions, e.g. `(false, 5)` constructs a tuple
2131
+ * or `Some(5)` constructs an `Option<i32>` and pairs them with their derived impl predicates.
2132
+ */
2133
+ fn point_at_specific_expr_if_possible (
2134
+ & self ,
2135
+ error : & mut traits:: FulfillmentError < ' tcx > ,
2136
+ expr : & ' tcx hir:: Expr < ' tcx > ,
2137
+ ) {
2138
+ let expr = match self
2139
+ . point_at_specific_expr_if_possible_for_predicate_obligation ( & error. obligation , expr)
2140
+ {
2141
+ Ok ( expr) => expr,
2142
+ Err ( expr) => expr,
2143
+ } ;
2144
+
2145
+ // update the error span.
2146
+ error. obligation . cause . span = expr
2147
+ . span
2148
+ . find_ancestor_in_same_ctxt ( error. obligation . cause . span )
2149
+ . unwrap_or ( error. obligation . cause . span ) ;
2150
+ }
2151
+
1967
2152
fn point_at_field_if_possible (
1968
2153
& self ,
1969
2154
error : & mut traits:: FulfillmentError < ' tcx > ,
@@ -2242,3 +2427,24 @@ fn find_param_in_ty<'tcx>(ty: Ty<'tcx>, param_to_point_at: ty::GenericArg<'tcx>)
2242
2427
}
2243
2428
false
2244
2429
}
2430
+
2431
+ fn find_param_def_in_ty_walker < ' tcx > (
2432
+ mut walk : TypeWalker < ' tcx > ,
2433
+ param_to_point_at : & ' tcx ty:: GenericParamDef ,
2434
+ ) -> bool {
2435
+ let param_to_point_at_param_ty = ty:: ParamTy :: for_def ( param_to_point_at) ;
2436
+ while let Some ( arg) = walk. next ( ) {
2437
+ match arg. unpack ( ) {
2438
+ ty:: GenericArgKind :: Type ( arg_ty) => match arg_ty. kind ( ) {
2439
+ ty:: Param ( arg_param_ty) => {
2440
+ if arg_param_ty == & param_to_point_at_param_ty {
2441
+ return true ;
2442
+ }
2443
+ }
2444
+ _ => { }
2445
+ } ,
2446
+ _ => { }
2447
+ }
2448
+ }
2449
+ false
2450
+ }
0 commit comments