@@ -83,7 +83,7 @@ use hir::def_id::DefId;
83
83
use infer:: { self , TypeOrigin } ;
84
84
use middle:: region;
85
85
use ty:: subst;
86
- use ty:: { self , Ty , TyCtxt , TypeFoldable } ;
86
+ use ty:: { self , TyCtxt , TypeFoldable } ;
87
87
use ty:: { Region , ReFree } ;
88
88
use ty:: error:: TypeError ;
89
89
@@ -462,52 +462,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
462
462
}
463
463
}
464
464
465
- fn report_type_error ( & self ,
466
- trace : TypeTrace < ' tcx > ,
467
- terr : & TypeError < ' tcx > )
468
- -> DiagnosticBuilder < ' tcx > {
469
- let ( expected, found) = match self . values_str ( & trace. values ) {
470
- Some ( v) => v,
471
- None => {
472
- return self . tcx . sess . diagnostic ( ) . struct_dummy ( ) ; /* derived error */
473
- }
474
- } ;
475
-
476
- let is_simple_error = if let & TypeError :: Sorts ( ref values) = terr {
477
- values. expected . is_primitive ( ) && values. found . is_primitive ( )
478
- } else {
479
- false
480
- } ;
481
-
482
- let mut err = struct_span_err ! ( self . tcx. sess,
483
- trace. origin. span( ) ,
484
- E0308 ,
485
- "{}" ,
486
- trace. origin) ;
487
-
488
- if !is_simple_error || check_old_school ( ) {
489
- err. note_expected_found ( & "type" , & expected, & found) ;
490
- }
491
-
492
- err. span_label ( trace. origin . span ( ) , & terr) ;
493
-
494
- self . check_and_note_conflicting_crates ( & mut err, terr, trace. origin . span ( ) ) ;
495
-
496
- match trace. origin {
497
- TypeOrigin :: MatchExpressionArm ( _, arm_span, source) => match source {
498
- hir:: MatchSource :: IfLetDesugar { ..} => {
499
- err. span_note ( arm_span, "`if let` arm with an incompatible type" ) ;
500
- }
501
- _ => {
502
- err. span_note ( arm_span, "match arm with an incompatible type" ) ;
503
- }
504
- } ,
505
- _ => ( )
506
- }
507
-
508
- err
509
- }
510
-
511
465
/// Adds a note if the types come from similarly named crates
512
466
fn check_and_note_conflicting_crates ( & self ,
513
467
err : & mut DiagnosticBuilder ,
@@ -550,42 +504,102 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
550
504
}
551
505
}
552
506
507
+ fn note_error_origin ( & self ,
508
+ err : & mut DiagnosticBuilder < ' tcx > ,
509
+ origin : & TypeOrigin )
510
+ {
511
+ match origin {
512
+ & TypeOrigin :: MatchExpressionArm ( _, arm_span, source) => match source {
513
+ hir:: MatchSource :: IfLetDesugar { ..} => {
514
+ err. span_note ( arm_span, "`if let` arm with an incompatible type" ) ;
515
+ }
516
+ _ => {
517
+ err. span_note ( arm_span, "match arm with an incompatible type" ) ;
518
+ }
519
+ } ,
520
+ _ => ( )
521
+ }
522
+ }
523
+
524
+ pub fn note_type_err ( & self ,
525
+ diag : & mut DiagnosticBuilder < ' tcx > ,
526
+ origin : TypeOrigin ,
527
+ values : Option < ValuePairs < ' tcx > > ,
528
+ terr : & TypeError < ' tcx > )
529
+ {
530
+ let expected_found = match values {
531
+ None => None ,
532
+ Some ( values) => match self . values_str ( & values) {
533
+ Some ( ( expected, found) ) => Some ( ( expected, found) ) ,
534
+ None => {
535
+ // Derived error. Cancel the emitter.
536
+ self . tcx . sess . diagnostic ( ) . cancel ( diag) ;
537
+ return
538
+ }
539
+ }
540
+ } ;
541
+
542
+ let span = origin. span ( ) ;
543
+
544
+ let mut is_simple_error = false ;
545
+
546
+ if let Some ( ( expected, found) ) = expected_found {
547
+ is_simple_error = if let & TypeError :: Sorts ( ref values) = terr {
548
+ values. expected . is_primitive ( ) && values. found . is_primitive ( )
549
+ } else {
550
+ false
551
+ } ;
552
+
553
+ if !is_simple_error || check_old_school ( ) {
554
+ diag. note_expected_found ( & "type" , & expected, & found) ;
555
+ }
556
+ }
557
+
558
+ if !is_simple_error && check_old_school ( ) {
559
+ diag. span_note ( span, & format ! ( "{}" , terr) ) ;
560
+ } else {
561
+ diag. span_label ( span, & terr) ;
562
+ }
563
+
564
+ self . note_error_origin ( diag, & origin) ;
565
+ self . check_and_note_conflicting_crates ( diag, terr, span) ;
566
+ self . tcx . note_and_explain_type_err ( diag, terr, span) ;
567
+ }
568
+
553
569
pub fn report_and_explain_type_error ( & self ,
554
570
trace : TypeTrace < ' tcx > ,
555
571
terr : & TypeError < ' tcx > )
556
- -> DiagnosticBuilder < ' tcx > {
557
- let span = trace. origin . span ( ) ;
558
- let mut err = self . report_type_error ( trace, terr) ;
559
- self . tcx . note_and_explain_type_err ( & mut err, terr, span) ;
560
- err
572
+ -> DiagnosticBuilder < ' tcx >
573
+ {
574
+ // FIXME: do we want to use a different error code for each origin?
575
+ let mut diag = struct_span_err ! (
576
+ self . tcx. sess, trace. origin. span( ) , E0308 ,
577
+ "{}" , trace. origin. as_failure_str( )
578
+ ) ;
579
+ self . note_type_err ( & mut diag, trace. origin , Some ( trace. values ) , terr) ;
580
+ diag
561
581
}
562
582
563
- /// Returns a string of the form "expected `{}`, found `{}`", or None if this is a derived
564
- /// error.
583
+ /// Returns a string of the form "expected `{}`, found `{}`".
565
584
fn values_str ( & self , values : & ValuePairs < ' tcx > ) -> Option < ( String , String ) > {
566
585
match * values {
567
586
infer:: Types ( ref exp_found) => self . expected_found_str ( exp_found) ,
568
587
infer:: TraitRefs ( ref exp_found) => self . expected_found_str ( exp_found) ,
569
- infer:: PolyTraitRefs ( ref exp_found) => self . expected_found_str ( exp_found)
588
+ infer:: PolyTraitRefs ( ref exp_found) => self . expected_found_str ( exp_found) ,
570
589
}
571
590
}
572
591
573
- fn expected_found_str < T : fmt:: Display + Resolvable < ' tcx > + TypeFoldable < ' tcx > > (
592
+ fn expected_found_str < T : fmt:: Display + TypeFoldable < ' tcx > > (
574
593
& self ,
575
594
exp_found : & ty:: error:: ExpectedFound < T > )
576
595
-> Option < ( String , String ) >
577
596
{
578
- let expected = exp_found. expected . resolve ( self ) ;
579
- if expected. references_error ( ) {
580
- return None ;
581
- }
582
-
583
- let found = exp_found. found . resolve ( self ) ;
584
- if found. references_error ( ) {
597
+ let exp_found = self . resolve_type_vars_if_possible ( exp_found) ;
598
+ if exp_found. references_error ( ) {
585
599
return None ;
586
600
}
587
601
588
- Some ( ( format ! ( "{}" , expected) , format ! ( "{}" , found) ) )
602
+ Some ( ( format ! ( "{}" , exp_found . expected) , format ! ( "{}" , exp_found . found) ) )
589
603
}
590
604
591
605
fn report_generic_bound_failure ( & self ,
@@ -1608,59 +1622,21 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
1608
1622
fn note_region_origin ( & self , err : & mut DiagnosticBuilder , origin : & SubregionOrigin < ' tcx > ) {
1609
1623
match * origin {
1610
1624
infer:: Subtype ( ref trace) => {
1611
- let desc = match trace. origin {
1612
- TypeOrigin :: Misc ( _) => {
1613
- "types are compatible"
1614
- }
1615
- TypeOrigin :: MethodCompatCheck ( _) => {
1616
- "method type is compatible with trait"
1617
- }
1618
- TypeOrigin :: ExprAssignable ( _) => {
1619
- "expression is assignable"
1620
- }
1621
- TypeOrigin :: RelateTraitRefs ( _) => {
1622
- "traits are compatible"
1623
- }
1624
- TypeOrigin :: RelateSelfType ( _) => {
1625
- "self type matches impl self type"
1626
- }
1627
- TypeOrigin :: RelateOutputImplTypes ( _) => {
1628
- "trait type parameters matches those \
1629
- specified on the impl"
1630
- }
1631
- TypeOrigin :: MatchExpressionArm ( _, _, _) => {
1632
- "match arms have compatible types"
1633
- }
1634
- TypeOrigin :: IfExpression ( _) => {
1635
- "if and else have compatible types"
1636
- }
1637
- TypeOrigin :: IfExpressionWithNoElse ( _) => {
1638
- "if may be missing an else clause"
1639
- }
1640
- TypeOrigin :: RangeExpression ( _) => {
1641
- "start and end of range have compatible types"
1642
- }
1643
- TypeOrigin :: EquatePredicate ( _) => {
1644
- "equality where clause is satisfied"
1645
- }
1646
- } ;
1647
-
1648
- match self . values_str ( & trace. values ) {
1649
- Some ( ( expected, found) ) => {
1650
- err. span_note (
1651
- trace. origin . span ( ) ,
1652
- & format ! ( "...so that {} (expected {}, found {})" ,
1653
- desc, expected, found) ) ;
1654
- }
1655
- None => {
1656
- // Really should avoid printing this error at
1657
- // all, since it is derived, but that would
1658
- // require more refactoring than I feel like
1659
- // doing right now. - nmatsakis
1660
- err. span_note (
1661
- trace. origin . span ( ) ,
1662
- & format ! ( "...so that {}" , desc) ) ;
1663
- }
1625
+ if let Some ( ( expected, found) ) = self . values_str ( & trace. values ) {
1626
+ // FIXME: do we want a "the" here?
1627
+ err. span_note (
1628
+ trace. origin . span ( ) ,
1629
+ & format ! ( "...so that {} (expected {}, found {})" ,
1630
+ trace. origin. as_requirement_str( ) , expected, found) ) ;
1631
+ } else {
1632
+ // FIXME: this really should be handled at some earlier stage. Our
1633
+ // handling of region checking when type errors are present is
1634
+ // *terrible*.
1635
+
1636
+ err. span_note (
1637
+ trace. origin . span ( ) ,
1638
+ & format ! ( "...so that {}" ,
1639
+ trace. origin. as_requirement_str( ) ) ) ;
1664
1640
}
1665
1641
}
1666
1642
infer:: Reborrow ( span) => {
@@ -1803,32 +1779,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
1803
1779
}
1804
1780
}
1805
1781
1806
- pub trait Resolvable < ' tcx > {
1807
- fn resolve < ' a , ' gcx > ( & self , infcx : & InferCtxt < ' a , ' gcx , ' tcx > ) -> Self ;
1808
- }
1809
-
1810
- impl < ' tcx > Resolvable < ' tcx > for Ty < ' tcx > {
1811
- fn resolve < ' a , ' gcx > ( & self , infcx : & InferCtxt < ' a , ' gcx , ' tcx > ) -> Ty < ' tcx > {
1812
- infcx. resolve_type_vars_if_possible ( self )
1813
- }
1814
- }
1815
-
1816
- impl < ' tcx > Resolvable < ' tcx > for ty:: TraitRef < ' tcx > {
1817
- fn resolve < ' a , ' gcx > ( & self , infcx : & InferCtxt < ' a , ' gcx , ' tcx > )
1818
- -> ty:: TraitRef < ' tcx > {
1819
- infcx. resolve_type_vars_if_possible ( self )
1820
- }
1821
- }
1822
-
1823
- impl < ' tcx > Resolvable < ' tcx > for ty:: PolyTraitRef < ' tcx > {
1824
- fn resolve < ' a , ' gcx > ( & self ,
1825
- infcx : & InferCtxt < ' a , ' gcx , ' tcx > )
1826
- -> ty:: PolyTraitRef < ' tcx >
1827
- {
1828
- infcx. resolve_type_vars_if_possible ( self )
1829
- }
1830
- }
1831
-
1832
1782
fn lifetimes_in_scope < ' a , ' gcx , ' tcx > ( tcx : TyCtxt < ' a , ' gcx , ' tcx > ,
1833
1783
scope_id : ast:: NodeId )
1834
1784
-> Vec < hir:: LifetimeDef > {
0 commit comments