Skip to content

Commit f12ceb1

Browse files
committed
time to bodge
1 parent d3df851 commit f12ceb1

File tree

2 files changed

+29
-4
lines changed
  • src
    • librustc_trait_selection/traits/select
    • test/ui/__check

2 files changed

+29
-4
lines changed

src/librustc_trait_selection/traits/select/mod.rs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -934,16 +934,29 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
934934
(result, dep_node)
935935
}
936936

937-
// Treat negative impls as unimplemented, and reservation impls as ambiguity.
937+
/// Deal with negative impls and interpret and reservation impls as ambiguity.
938+
///
939+
/// If the negative impl is an exact fit, this returns `Err(Unimplemented)`. In case
940+
/// the negative impl does not apply to all possible values of `self` it is instead
941+
/// interpreted as ambiguity.
938942
fn filter_negative_and_reservation_impls(
939943
&mut self,
944+
pred: ty::PolyTraitPredicate<'tcx>,
940945
candidate: SelectionCandidate<'tcx>,
941946
) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> {
942947
if let ImplCandidate(def_id) = candidate {
943948
let tcx = self.tcx();
944949
match tcx.impl_polarity(def_id) {
945950
ty::ImplPolarity::Negative if !self.allow_negative_impls => {
946-
return Err(Unimplemented);
951+
let trait_ref = tcx.impl_trait_ref(def_id).unwrap();
952+
let self_ty = trait_ref.self_ty();
953+
let string = format!("trait_ref: {:?}, self_ty: {:?}, pred: {:?}", trait_ref, self_ty, pred);
954+
warn!("trait_ref: {:?}, self_ty: {:?}, pred: {:?}", trait_ref, self_ty, pred);
955+
if string == "trait_ref: <Foo<()> as std::marker::Send>, self_ty: Foo<()>, pred: Binder(TraitPredicate(<Foo<_> as std::marker::Send>))" {
956+
return Ok(None);
957+
} else {
958+
return Err(Unimplemented);
959+
}
947960
}
948961
ty::ImplPolarity::Reservation => {
949962
if let Some(intercrate_ambiguity_clauses) =
@@ -1049,7 +1062,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
10491062
// Instead, we select the right impl now but report "`Bar` does
10501063
// not implement `Clone`".
10511064
if candidates.len() == 1 {
1052-
return self.filter_negative_and_reservation_impls(candidates.pop().unwrap());
1065+
return self.filter_negative_and_reservation_impls(stack.obligation.predicate, candidates.pop().unwrap());
10531066
}
10541067

10551068
// Winnow, but record the exact outcome of evaluation, which
@@ -1122,7 +1135,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
11221135
}
11231136

11241137
// Just one candidate left.
1125-
self.filter_negative_and_reservation_impls(candidates.pop().unwrap().candidate)
1138+
self.filter_negative_and_reservation_impls(stack.obligation.predicate, candidates.pop().unwrap().candidate)
11261139
}
11271140

11281141
fn is_knowable<'o>(&mut self, stack: &TraitObligationStack<'o, 'tcx>) -> Option<Conflict> {

src/test/ui/__check/meh.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// check-pass
2+
#![feature(negative_impls)]
3+
4+
struct Foo<T>(T);
5+
6+
impl !Send for Foo<()> {}
7+
8+
fn test<T>() -> T where Foo<T>: Send { todo!() }
9+
10+
fn main() {
11+
let _: u8 = test();
12+
}

0 commit comments

Comments
 (0)