@@ -43,6 +43,8 @@ use crate::hir;
4343use rustc_data_structures:: bit_set:: GrowableBitSet ;
4444use rustc_data_structures:: sync:: Lock ;
4545use rustc_target:: spec:: abi:: Abi ;
46+ use syntax:: attr;
47+ use syntax:: symbol:: sym;
4648use std:: cell:: { Cell , RefCell } ;
4749use std:: cmp;
4850use std:: fmt:: { self , Display } ;
@@ -99,6 +101,9 @@ pub enum IntercrateAmbiguityCause {
99101 trait_desc : String ,
100102 self_desc : Option < String > ,
101103 } ,
104+ ReservationImpl {
105+ message : String
106+ } ,
102107}
103108
104109impl IntercrateAmbiguityCause {
@@ -139,6 +144,11 @@ impl IntercrateAmbiguityCause {
139144 trait_desc, self_desc
140145 )
141146 }
147+ & IntercrateAmbiguityCause :: ReservationImpl {
148+ ref message
149+ } => {
150+ message. clone ( )
151+ }
142152 }
143153 }
144154}
@@ -1326,17 +1336,38 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
13261336 ( result, dep_node)
13271337 }
13281338
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 ,
13321342 candidate : SelectionCandidate < ' tcx > ,
13331343 ) -> SelectionResult < ' tcx , SelectionCandidate < ' tcx > > {
13341344 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+ } ;
13401371 }
13411372 Ok ( Some ( candidate) )
13421373 }
@@ -1453,7 +1484,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
14531484 // Instead, we select the right impl now but report `Bar does
14541485 // not implement Clone`.
14551486 if candidates. len ( ) == 1 {
1456- return self . filter_negative_impls ( candidates. pop ( ) . unwrap ( ) ) ;
1487+ return self . filter_negative_and_reservation_impls ( candidates. pop ( ) . unwrap ( ) ) ;
14571488 }
14581489
14591490 // Winnow, but record the exact outcome of evaluation, which
@@ -1528,7 +1559,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
15281559 }
15291560
15301561 // Just one candidate left.
1531- self . filter_negative_impls ( candidates. pop ( ) . unwrap ( ) . candidate )
1562+ self . filter_negative_and_reservation_impls ( candidates. pop ( ) . unwrap ( ) . candidate )
15321563 }
15331564
15341565 fn is_knowable < ' o > ( & mut self , stack : & TraitObligationStack < ' o , ' tcx > ) -> Option < Conflict > {
@@ -3728,6 +3759,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
37283759 return Err ( ( ) ) ;
37293760 }
37303761
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+
37313769 debug ! ( "match_impl: success impl_substs={:?}" , impl_substs) ;
37323770 Ok ( Normalized {
37333771 value : impl_substs,
0 commit comments