use crate::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable};
use crate::hir;
-use rustc_data_structures::bit_set::GrowableBitSet;
+use rustc_index::bit_set::GrowableBitSet;
use rustc_data_structures::sync::Lock;
use rustc_target::spec::abi::Abi;
+use syntax::attr;
+use syntax::symbol::sym;
use std::cell::{Cell, RefCell};
use std::cmp;
use std::fmt::{self, Display};
trait_desc: String,
self_desc: Option<String>,
},
+ ReservationImpl {
+ message: String
+ },
}
impl IntercrateAmbiguityCause {
trait_desc, self_desc
)
}
+ &IntercrateAmbiguityCause::ReservationImpl {
+ ref message
+ } => {
+ message.clone()
+ }
}
}
}
(result, dep_node)
}
- // Treat negative impls as unimplemented
- fn filter_negative_impls(
- &self,
+ // Treat negative impls as unimplemented, and reservation impls as ambiguity.
+ fn filter_negative_and_reservation_impls(
+ &mut self,
candidate: SelectionCandidate<'tcx>,
) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> {
if let ImplCandidate(def_id) = candidate {
- if !self.allow_negative_impls
- && self.tcx().impl_polarity(def_id) == hir::ImplPolarity::Negative
- {
- return Err(Unimplemented);
- }
+ let tcx = self.tcx();
+ match tcx.impl_polarity(def_id) {
+ ty::ImplPolarity::Negative if !self.allow_negative_impls => {
+ return Err(Unimplemented);
+ }
+ ty::ImplPolarity::Reservation => {
+ if let Some(intercrate_ambiguity_clauses)
+ = &mut self.intercrate_ambiguity_causes
+ {
+ let attrs = tcx.get_attrs(def_id);
+ let attr = attr::find_by_name(&attrs, sym::rustc_reservation_impl);
+ let value = attr.and_then(|a| a.value_str());
+ if let Some(value) = value {
+ debug!("filter_negative_and_reservation_impls: \
+ reservation impl ambiguity on {:?}", def_id);
+ intercrate_ambiguity_clauses.push(
+ IntercrateAmbiguityCause::ReservationImpl {
+ message: value.to_string()
+ }
+ );
+ }
+ }
+ return Ok(None);
+ }
+ _ => {}
+ };
}
Ok(Some(candidate))
}
// Instead, we select the right impl now but report `Bar does
// not implement Clone`.
if candidates.len() == 1 {
- return self.filter_negative_impls(candidates.pop().unwrap());
+ return self.filter_negative_and_reservation_impls(candidates.pop().unwrap());
}
// Winnow, but record the exact outcome of evaluation, which
}
// Just one candidate left.
- self.filter_negative_impls(candidates.pop().unwrap().candidate)
+ self.filter_negative_and_reservation_impls(candidates.pop().unwrap().candidate)
}
fn is_knowable<'o>(&mut self, stack: &TraitObligationStack<'o, 'tcx>) -> Option<Conflict> {
"assemble_unboxed_candidates: kind={:?} obligation={:?}",
kind, obligation
);
- match self.infcx.closure_kind(closure_def_id, closure_substs) {
+ match self.infcx.closure_kind(
+ closure_def_id,
+ closure_substs
+ ) {
Some(closure_kind) => {
debug!(
"assemble_unboxed_candidates: closure_kind = {:?}",
if other.evaluation.must_apply_modulo_regions() {
match victim.candidate {
ImplCandidate(victim_def) => {
- let tcx = self.tcx().global_tcx();
+ let tcx = self.tcx();
return tcx.specializes((other_def, victim_def))
|| tcx.impls_are_allowed_to_overlap(
other_def, victim_def).is_some();
ty::Closure(def_id, substs) => {
// (*) binder moved here
Where(ty::Binder::bind(
- substs.upvar_tys(def_id, self.tcx()).collect(),
+ substs.as_closure().upvar_tys(def_id, self.tcx()).collect(),
))
}
tys.iter().map(|k| k.expect_ty()).collect()
}
- ty::Closure(def_id, ref substs) => substs.upvar_tys(def_id, self.tcx()).collect(),
+ ty::Closure(def_id, ref substs) => substs.as_closure()
+ .upvar_tys(def_id, self.tcx())
+ .collect(),
ty::Generator(def_id, ref substs, _) => {
let witness = substs.witness(def_id, self.tcx());
)?);
// FIXME: chalk
+
if !self.tcx().sess.opts.debugging_opts.chalk {
obligations.push(Obligation::new(
obligation.cause.clone(),
obligation.param_env,
- ty::Predicate::ClosureKind(closure_def_id, substs, kind),
+ ty::Predicate::ClosureKind(
+ closure_def_id,
+ substs,
+ kind
+ ),
));
}
Ok(VtableClosureData {
closure_def_id,
- substs: substs.clone(),
+ substs: substs,
nested: obligations,
})
}
return Err(());
}
+ if self.intercrate.is_none()
+ && self.tcx().impl_polarity(impl_def_id) == ty::ImplPolarity::Reservation
+ {
+ debug!("match_impl: reservation impls only apply in intercrate mode");
+ return Err(());
+ }
+
debug!("match_impl: success impl_substs={:?}", impl_substs);
Ok(Normalized {
value: impl_substs,
&mut self,
obligation: &TraitObligation<'tcx>,
closure_def_id: DefId,
- substs: ty::ClosureSubsts<'tcx>,
+ substs: SubstsRef<'tcx>,
) -> ty::PolyTraitRef<'tcx> {
debug!(
"closure_trait_ref_unnormalized(obligation={:?}, closure_def_id={:?}, substs={:?})",