@@ -24,8 +24,10 @@ use rustc_infer::infer::error_reporting::{FailureCode, ObligationCauseExt};
2424use rustc_infer:: infer:: type_variable:: { TypeVariableOrigin , TypeVariableOriginKind } ;
2525use rustc_infer:: infer:: InferOk ;
2626use rustc_infer:: infer:: TypeTrace ;
27+ use rustc_infer:: traits:: PredicateObligation ;
2728use rustc_middle:: ty:: adjustment:: AllowTwoPhase ;
2829use rustc_middle:: ty:: visit:: TypeVisitable ;
30+ use rustc_middle:: ty:: walk:: TypeWalker ;
2931use rustc_middle:: ty:: { self , DefIdTree , IsSuggestable , Ty , TypeSuperVisitable , TypeVisitor } ;
3032use rustc_session:: Session ;
3133use rustc_span:: symbol:: { kw, Ident } ;
@@ -523,7 +525,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
523525 // Sometimes macros mess up the spans, so do not normalize the
524526 // arg span to equal the error span, because that's less useful
525527 // 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+ }
527533 } ;
528534
529535 // 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> {
776782 // can be collated pretty easily if needed.
777783
778784 // 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[ ..]
782787 {
783788 let ( formal_ty, expected_ty) = formal_and_expected_inputs[ * expected_idx] ;
784789 let ( provided_ty, provided_arg_span) = provided_arg_tys[ * provided_idx] ;
@@ -1520,25 +1525,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
15201525 // Our block must be a `assign desugar local; assignment`
15211526 if let Some ( hir:: Node :: Block ( hir:: Block {
15221527 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+ } ] ,
15421543 ..
15431544 } ) ) = self . tcx . hir ( ) . find ( blk. hir_id )
15441545 {
@@ -1946,7 +1947,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
19461947 if let [ ( idx, _) ] = args_referencing_param. as_slice ( )
19471948 && let Some ( arg) = receiver
19481949 . map_or ( args. get ( * idx) , |rcvr| if * idx == 0 { Some ( rcvr) } else { args. get ( * idx - 1 ) } ) {
1950+
19491951 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+
19501958 error. obligation . cause . map_code ( |parent_code| {
19511959 ObligationCauseCode :: FunctionArgumentObligation {
19521960 arg_hir_id : arg. hir_id ,
@@ -1964,6 +1972,183 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
19641972 false
19651973 }
19661974
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+
19672152 fn point_at_field_if_possible (
19682153 & self ,
19692154 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>)
22422427 }
22432428 false
22442429}
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