@@ -83,7 +83,7 @@ use hir::def_id::DefId;
8383use infer:: { self , TypeOrigin } ;
8484use middle:: region;
8585use ty:: subst;
86- use ty:: { self , Ty , TyCtxt , TypeFoldable } ;
86+ use ty:: { self , TyCtxt , TypeFoldable } ;
8787use ty:: { Region , ReFree } ;
8888use ty:: error:: TypeError ;
8989
@@ -462,52 +462,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
462462 }
463463 }
464464
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-
511465 /// Adds a note if the types come from similarly named crates
512466 fn check_and_note_conflicting_crates ( & self ,
513467 err : & mut DiagnosticBuilder ,
@@ -550,42 +504,102 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
550504 }
551505 }
552506
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+
553569 pub fn report_and_explain_type_error ( & self ,
554570 trace : TypeTrace < ' tcx > ,
555571 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
561581 }
562582
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 `{}`".
565584 fn values_str ( & self , values : & ValuePairs < ' tcx > ) -> Option < ( String , String ) > {
566585 match * values {
567586 infer:: Types ( ref exp_found) => self . expected_found_str ( exp_found) ,
568587 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) ,
570589 }
571590 }
572591
573- fn expected_found_str < T : fmt:: Display + Resolvable < ' tcx > + TypeFoldable < ' tcx > > (
592+ fn expected_found_str < T : fmt:: Display + TypeFoldable < ' tcx > > (
574593 & self ,
575594 exp_found : & ty:: error:: ExpectedFound < T > )
576595 -> Option < ( String , String ) >
577596 {
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 ( ) {
585599 return None ;
586600 }
587601
588- Some ( ( format ! ( "{}" , expected) , format ! ( "{}" , found) ) )
602+ Some ( ( format ! ( "{}" , exp_found . expected) , format ! ( "{}" , exp_found . found) ) )
589603 }
590604
591605 fn report_generic_bound_failure ( & self ,
@@ -1608,59 +1622,21 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
16081622 fn note_region_origin ( & self , err : & mut DiagnosticBuilder , origin : & SubregionOrigin < ' tcx > ) {
16091623 match * origin {
16101624 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( ) ) ) ;
16641640 }
16651641 }
16661642 infer:: Reborrow ( span) => {
@@ -1803,32 +1779,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
18031779 }
18041780}
18051781
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-
18321782fn lifetimes_in_scope < ' a , ' gcx , ' tcx > ( tcx : TyCtxt < ' a , ' gcx , ' tcx > ,
18331783 scope_id : ast:: NodeId )
18341784 -> Vec < hir:: LifetimeDef > {
0 commit comments