@@ -43,6 +43,8 @@ use crate::hir;
43
43
use rustc_data_structures:: bit_set:: GrowableBitSet ;
44
44
use rustc_data_structures:: sync:: Lock ;
45
45
use rustc_target:: spec:: abi:: Abi ;
46
+ use syntax:: attr;
47
+ use syntax:: symbol:: sym;
46
48
use std:: cell:: { Cell , RefCell } ;
47
49
use std:: cmp;
48
50
use std:: fmt:: { self , Display } ;
@@ -99,6 +101,9 @@ pub enum IntercrateAmbiguityCause {
99
101
trait_desc : String ,
100
102
self_desc : Option < String > ,
101
103
} ,
104
+ ReservationImpl {
105
+ message : String
106
+ } ,
102
107
}
103
108
104
109
impl IntercrateAmbiguityCause {
@@ -139,6 +144,11 @@ impl IntercrateAmbiguityCause {
139
144
trait_desc, self_desc
140
145
)
141
146
}
147
+ & IntercrateAmbiguityCause :: ReservationImpl {
148
+ ref message
149
+ } => {
150
+ message. clone ( )
151
+ }
142
152
}
143
153
}
144
154
}
@@ -1326,17 +1336,38 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1326
1336
( result, dep_node)
1327
1337
}
1328
1338
1329
- // Treat negative impls as unimplemented
1330
- fn filter_negative_impls (
1331
- & self ,
1339
+ // Treat negative impls as unimplemented, and reservation impls as ambiguity.
1340
+ fn filter_negative_and_reservation_impls (
1341
+ & mut self ,
1332
1342
candidate : SelectionCandidate < ' tcx > ,
1333
1343
) -> SelectionResult < ' tcx , SelectionCandidate < ' tcx > > {
1334
1344
if let ImplCandidate ( def_id) = candidate {
1335
- if !self . allow_negative_impls
1336
- && self . tcx ( ) . impl_polarity ( def_id) == hir:: ImplPolarity :: Negative
1337
- {
1338
- return Err ( Unimplemented ) ;
1339
- }
1345
+ let tcx = self . tcx ( ) ;
1346
+ match tcx. impl_polarity ( def_id) {
1347
+ ty:: ImplPolarity :: Negative if !self . allow_negative_impls => {
1348
+ return Err ( Unimplemented ) ;
1349
+ }
1350
+ ty:: ImplPolarity :: Reservation => {
1351
+ if let Some ( intercrate_ambiguity_clauses)
1352
+ = & mut self . intercrate_ambiguity_causes
1353
+ {
1354
+ let attrs = tcx. get_attrs ( def_id) ;
1355
+ let attr = attr:: find_by_name ( & attrs, sym:: rustc_reservation_impl) ;
1356
+ let value = attr. and_then ( |a| a. value_str ( ) ) ;
1357
+ if let Some ( value) = value {
1358
+ debug ! ( "filter_negative_and_reservation_impls: \
1359
+ reservation impl ambiguity on {:?}", def_id) ;
1360
+ intercrate_ambiguity_clauses. push (
1361
+ IntercrateAmbiguityCause :: ReservationImpl {
1362
+ message : value. to_string ( )
1363
+ }
1364
+ ) ;
1365
+ }
1366
+ }
1367
+ return Ok ( None ) ;
1368
+ }
1369
+ _ => { }
1370
+ } ;
1340
1371
}
1341
1372
Ok ( Some ( candidate) )
1342
1373
}
@@ -1453,7 +1484,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1453
1484
// Instead, we select the right impl now but report `Bar does
1454
1485
// not implement Clone`.
1455
1486
if candidates. len ( ) == 1 {
1456
- return self . filter_negative_impls ( candidates. pop ( ) . unwrap ( ) ) ;
1487
+ return self . filter_negative_and_reservation_impls ( candidates. pop ( ) . unwrap ( ) ) ;
1457
1488
}
1458
1489
1459
1490
// Winnow, but record the exact outcome of evaluation, which
@@ -1528,7 +1559,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1528
1559
}
1529
1560
1530
1561
// Just one candidate left.
1531
- self . filter_negative_impls ( candidates. pop ( ) . unwrap ( ) . candidate )
1562
+ self . filter_negative_and_reservation_impls ( candidates. pop ( ) . unwrap ( ) . candidate )
1532
1563
}
1533
1564
1534
1565
fn is_knowable < ' o > ( & mut self , stack : & TraitObligationStack < ' o , ' tcx > ) -> Option < Conflict > {
@@ -3728,6 +3759,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
3728
3759
return Err ( ( ) ) ;
3729
3760
}
3730
3761
3762
+ if self . intercrate . is_none ( )
3763
+ && self . tcx ( ) . impl_polarity ( impl_def_id) == ty:: ImplPolarity :: Reservation
3764
+ {
3765
+ debug ! ( "match_impl: reservation impls only apply in intercrate mode" ) ;
3766
+ return Err ( ( ) ) ;
3767
+ }
3768
+
3731
3769
debug ! ( "match_impl: success impl_substs={:?}" , impl_substs) ;
3732
3770
Ok ( Normalized {
3733
3771
value : impl_substs,
0 commit comments