@@ -36,37 +36,51 @@ use util::nodemap::{FnvHashMap, FnvHashSet};
36
36
use std:: cmp;
37
37
use std:: fmt;
38
38
use syntax:: attr:: { AttributeMethods , AttrMetaMethods } ;
39
+ use syntax:: ast;
39
40
use syntax:: codemap:: Span ;
40
41
use syntax:: errors:: DiagnosticBuilder ;
41
42
42
43
#[ derive( Debug , PartialEq , Eq , Hash ) ]
43
44
pub struct TraitErrorKey < ' tcx > {
44
45
span : Span ,
46
+ warning_node_id : Option < ast:: NodeId > ,
45
47
predicate : ty:: Predicate < ' tcx >
46
48
}
47
49
48
50
impl < ' tcx > TraitErrorKey < ' tcx > {
49
51
fn from_error < ' a > ( infcx : & InferCtxt < ' a , ' tcx > ,
50
- e : & FulfillmentError < ' tcx > ) -> Self {
52
+ e : & FulfillmentError < ' tcx > ,
53
+ warning_node_id : Option < ast:: NodeId > ) -> Self {
51
54
let predicate =
52
55
infcx. resolve_type_vars_if_possible ( & e. obligation . predicate ) ;
53
56
TraitErrorKey {
54
57
span : e. obligation . cause . span ,
55
- predicate : infcx. tcx . erase_regions ( & predicate)
58
+ predicate : infcx. tcx . erase_regions ( & predicate) ,
59
+ warning_node_id : warning_node_id
56
60
}
57
61
}
58
62
}
59
63
60
64
pub fn report_fulfillment_errors < ' a , ' tcx > ( infcx : & InferCtxt < ' a , ' tcx > ,
61
65
errors : & Vec < FulfillmentError < ' tcx > > ) {
62
66
for error in errors {
63
- report_fulfillment_error ( infcx, error) ;
67
+ report_fulfillment_error ( infcx, error, None ) ;
68
+ }
69
+ }
70
+
71
+ pub fn report_fulfillment_errors_as_warnings < ' a , ' tcx > ( infcx : & InferCtxt < ' a , ' tcx > ,
72
+ errors : & Vec < FulfillmentError < ' tcx > > ,
73
+ node_id : ast:: NodeId )
74
+ {
75
+ for error in errors {
76
+ report_fulfillment_error ( infcx, error, Some ( node_id) ) ;
64
77
}
65
78
}
66
79
67
80
fn report_fulfillment_error < ' a , ' tcx > ( infcx : & InferCtxt < ' a , ' tcx > ,
68
- error : & FulfillmentError < ' tcx > ) {
69
- let error_key = TraitErrorKey :: from_error ( infcx, error) ;
81
+ error : & FulfillmentError < ' tcx > ,
82
+ warning_node_id : Option < ast:: NodeId > ) {
83
+ let error_key = TraitErrorKey :: from_error ( infcx, error, warning_node_id) ;
70
84
debug ! ( "report_fulfillment_errors({:?}) - key={:?}" ,
71
85
error, error_key) ;
72
86
if !infcx. reported_trait_errors . borrow_mut ( ) . insert ( error_key) {
@@ -75,10 +89,10 @@ fn report_fulfillment_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
75
89
}
76
90
match error. code {
77
91
FulfillmentErrorCode :: CodeSelectionError ( ref e) => {
78
- report_selection_error ( infcx, & error. obligation , e) ;
92
+ report_selection_error ( infcx, & error. obligation , e, warning_node_id ) ;
79
93
}
80
94
FulfillmentErrorCode :: CodeProjectionError ( ref e) => {
81
- report_projection_error ( infcx, & error. obligation , e) ;
95
+ report_projection_error ( infcx, & error. obligation , e, warning_node_id ) ;
82
96
}
83
97
FulfillmentErrorCode :: CodeAmbiguity => {
84
98
maybe_report_ambiguity ( infcx, & error. obligation ) ;
@@ -88,18 +102,29 @@ fn report_fulfillment_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
88
102
89
103
pub fn report_projection_error < ' a , ' tcx > ( infcx : & InferCtxt < ' a , ' tcx > ,
90
104
obligation : & PredicateObligation < ' tcx > ,
91
- error : & MismatchedProjectionTypes < ' tcx > )
105
+ error : & MismatchedProjectionTypes < ' tcx > ,
106
+ warning_node_id : Option < ast:: NodeId > )
92
107
{
93
108
let predicate =
94
109
infcx. resolve_type_vars_if_possible ( & obligation. predicate ) ;
95
110
96
111
if !predicate. references_error ( ) {
97
- let mut err = struct_span_err ! ( infcx. tcx. sess, obligation. cause. span, E0271 ,
98
- "type mismatch resolving `{}`: {}" ,
99
- predicate,
100
- error. err) ;
101
- note_obligation_cause ( infcx, & mut err, obligation) ;
102
- err. emit ( ) ;
112
+ if let Some ( warning_node_id) = warning_node_id {
113
+ infcx. tcx . sess . add_lint (
114
+ :: lint:: builtin:: UNSIZED_IN_TUPLE ,
115
+ warning_node_id,
116
+ obligation. cause . span ,
117
+ format ! ( "type mismatch resolving `{}`: {}" ,
118
+ predicate,
119
+ error. err) ) ;
120
+ } else {
121
+ let mut err = struct_span_err ! ( infcx. tcx. sess, obligation. cause. span, E0271 ,
122
+ "type mismatch resolving `{}`: {}" ,
123
+ predicate,
124
+ error. err) ;
125
+ note_obligation_cause ( infcx, & mut err, obligation) ;
126
+ err. emit ( ) ;
127
+ }
103
128
}
104
129
}
105
130
@@ -383,7 +408,8 @@ pub fn recursive_type_with_infinite_size_error<'tcx>(tcx: &TyCtxt<'tcx>,
383
408
384
409
pub fn report_selection_error < ' a , ' tcx > ( infcx : & InferCtxt < ' a , ' tcx > ,
385
410
obligation : & PredicateObligation < ' tcx > ,
386
- error : & SelectionError < ' tcx > )
411
+ error : & SelectionError < ' tcx > ,
412
+ warning_node_id : Option < ast:: NodeId > )
387
413
{
388
414
match * error {
389
415
SelectionError :: Unimplemented => {
@@ -401,6 +427,17 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
401
427
402
428
if !infcx. tcx . sess . has_errors ( ) || !trait_predicate. references_error ( ) {
403
429
let trait_ref = trait_predicate. to_poly_trait_ref ( ) ;
430
+
431
+ if let Some ( warning_node_id) = warning_node_id {
432
+ infcx. tcx . sess . add_lint (
433
+ :: lint:: builtin:: UNSIZED_IN_TUPLE ,
434
+ warning_node_id,
435
+ obligation. cause . span ,
436
+ format ! ( "the trait bound `{}` is not satisfied" ,
437
+ trait_ref. to_predicate( ) ) ) ;
438
+ return ;
439
+ }
440
+
404
441
let mut err = struct_span_err ! (
405
442
infcx. tcx. sess, obligation. cause. span, E0277 ,
406
443
"the trait bound `{}` is not satisfied" ,
@@ -480,12 +517,15 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
480
517
ty:: Predicate :: ObjectSafe ( trait_def_id) => {
481
518
let violations = object_safety_violations (
482
519
infcx. tcx , trait_def_id) ;
483
- let mut err = report_object_safety_error ( infcx. tcx ,
484
- obligation. cause . span ,
485
- trait_def_id,
486
- violations) ;
487
- note_obligation_cause ( infcx, & mut err, obligation) ;
488
- err. emit ( ) ;
520
+ let err = report_object_safety_error ( infcx. tcx ,
521
+ obligation. cause . span ,
522
+ trait_def_id,
523
+ warning_node_id,
524
+ violations) ;
525
+ if let Some ( mut err) = err {
526
+ note_obligation_cause ( infcx, & mut err, obligation) ;
527
+ err. emit ( ) ;
528
+ }
489
529
}
490
530
491
531
ty:: Predicate :: ClosureKind ( closure_def_id, kind) => {
@@ -514,6 +554,13 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
514
554
"WF predicate not satisfied for {:?}" ,
515
555
ty) ;
516
556
}
557
+
558
+ ty:: Predicate :: Rfc1592 ( ref data) => {
559
+ span_bug ! (
560
+ obligation. cause. span,
561
+ "RFC1592 predicate not satisfied for {:?}" ,
562
+ data) ;
563
+ }
517
564
}
518
565
}
519
566
}
@@ -537,58 +584,84 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
537
584
538
585
TraitNotObjectSafe ( did) => {
539
586
let violations = object_safety_violations ( infcx. tcx , did) ;
540
- let mut err = report_object_safety_error ( infcx. tcx , obligation. cause . span , did,
541
- violations) ;
542
- note_obligation_cause ( infcx, & mut err, obligation) ;
543
- err. emit ( ) ;
587
+ let err = report_object_safety_error ( infcx. tcx , obligation. cause . span , did,
588
+ warning_node_id,
589
+ violations) ;
590
+ if let Some ( mut err) = err {
591
+ note_obligation_cause ( infcx, & mut err, obligation) ;
592
+ err. emit ( ) ;
593
+ }
544
594
}
545
595
}
546
596
}
547
597
548
598
pub fn report_object_safety_error < ' tcx > ( tcx : & TyCtxt < ' tcx > ,
549
599
span : Span ,
550
600
trait_def_id : DefId ,
601
+ warning_node_id : Option < ast:: NodeId > ,
551
602
violations : Vec < ObjectSafetyViolation > )
552
- -> DiagnosticBuilder < ' tcx >
603
+ -> Option < DiagnosticBuilder < ' tcx > >
553
604
{
554
- let mut err = struct_span_err ! (
555
- tcx. sess, span, E0038 ,
556
- "the trait `{}` cannot be made into an object" ,
557
- tcx. item_path_str( trait_def_id) ) ;
605
+ let mut err = match warning_node_id {
606
+ Some ( _) => None ,
607
+ None => {
608
+ Some ( struct_span_err ! (
609
+ tcx. sess, span, E0038 ,
610
+ "the trait `{}` cannot be made into an object" ,
611
+ tcx. item_path_str( trait_def_id) ) )
612
+ }
613
+ } ;
558
614
559
615
let mut reported_violations = FnvHashSet ( ) ;
560
616
for violation in violations {
561
617
if !reported_violations. insert ( violation. clone ( ) ) {
562
618
continue ;
563
619
}
564
- match violation {
620
+ let buf;
621
+ let note = match violation {
565
622
ObjectSafetyViolation :: SizedSelf => {
566
- err . note ( "the trait cannot require that `Self : Sized`" ) ;
623
+ "the trait cannot require that `Self : Sized`"
567
624
}
568
625
569
626
ObjectSafetyViolation :: SupertraitSelf => {
570
- err . note ( "the trait cannot use `Self` as a type parameter \
571
- in the supertrait listing") ;
627
+ "the trait cannot use `Self` as a type parameter \
628
+ in the supertrait listing"
572
629
}
573
630
574
631
ObjectSafetyViolation :: Method ( method,
575
632
MethodViolationCode :: StaticMethod ) => {
576
- err. note ( & format ! ( "method `{}` has no receiver" ,
577
- method. name) ) ;
633
+ buf = format ! ( "method `{}` has no receiver" ,
634
+ method. name) ;
635
+ & buf
578
636
}
579
637
580
638
ObjectSafetyViolation :: Method ( method,
581
639
MethodViolationCode :: ReferencesSelf ) => {
582
- err . note ( & format ! ( "method `{}` references the `Self` type \
640
+ buf = format ! ( "method `{}` references the `Self` type \
583
641
in its arguments or return type",
584
- method. name) ) ;
642
+ method. name) ;
643
+ & buf
585
644
}
586
645
587
646
ObjectSafetyViolation :: Method ( method,
588
647
MethodViolationCode :: Generic ) => {
589
- err. note ( & format ! ( "method `{}` has generic type parameters" ,
590
- method. name) ) ;
648
+ buf = format ! ( "method `{}` has generic type parameters" ,
649
+ method. name) ;
650
+ & buf
591
651
}
652
+ } ;
653
+ match ( warning_node_id, & mut err) {
654
+ ( Some ( node_id) , & mut None ) => {
655
+ tcx. sess . add_lint (
656
+ :: lint:: builtin:: OBJECT_UNSAFE_FRAGMENT ,
657
+ node_id,
658
+ span,
659
+ note. to_string ( ) ) ;
660
+ }
661
+ ( None , & mut Some ( ref mut err) ) => {
662
+ err. note ( note) ;
663
+ }
664
+ _ => unreachable ! ( )
592
665
}
593
666
}
594
667
err
@@ -764,6 +837,9 @@ fn note_obligation_cause_code<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>,
764
837
ObligationCauseCode :: SliceOrArrayElem => {
765
838
err. note ( "slice and array elements must have `Sized` type" ) ;
766
839
}
840
+ ObligationCauseCode :: TupleElem => {
841
+ err. note ( "tuple elements must have `Sized` type" ) ;
842
+ }
767
843
ObligationCauseCode :: ProjectionWf ( data) => {
768
844
err. note ( & format ! ( "required so that the projection `{}` is well-formed" ,
769
845
data) ) ;
0 commit comments