Skip to content

Commit d96faef

Browse files
committed
Where bounds are checked on inherent impls
1 parent f4bd1e1 commit d96faef

File tree

3 files changed

+61
-2
lines changed

3 files changed

+61
-2
lines changed

compiler/rustc_trait_selection/src/traits/coherence.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
use crate::infer::outlives::env::OutlivesEnvironment;
88
use crate::infer::{CombinedSnapshot, InferOk, RegionckMode};
99
use crate::traits::select::IntercrateAmbiguityCause;
10-
use crate::traits::util::impl_trait_ref_and_oblig;
10+
use crate::traits::util::{impl_trait_ref_and_oblig, inherent_impl_and_oblig};
1111
use crate::traits::SkipLeakCheck;
1212
use crate::traits::{
1313
self, FulfillmentContext, Normalized, Obligation, ObligationCause, PredicateObligation,
@@ -338,7 +338,13 @@ fn impl_subject_and_obligations<'cx, 'tcx>(
338338

339339
(ImplSubject::Trait(impl2_trait_ref), Box::new(obligations))
340340
} else {
341-
(infcx.tcx.impl_subject(impl2_def_id), Box::new(iter::empty()))
341+
// Attempt to prove that impl2 applies, given all of the above.
342+
let selcx = &mut SelectionContext::new(&infcx);
343+
let impl2_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl2_def_id);
344+
let (impl2_ty, obligations) =
345+
inherent_impl_and_oblig(selcx, impl_env, impl2_def_id, impl2_substs);
346+
347+
(ImplSubject::Inherent(impl2_ty), Box::new(obligations))
342348
}
343349
}
344350

compiler/rustc_trait_selection/src/traits/util.rs

+28
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,34 @@ pub fn impl_trait_ref_and_oblig<'a, 'tcx>(
218218
(impl_trait_ref, impl_obligations)
219219
}
220220

221+
/// Instantiate all bound parameters of the impl with the given substs,
222+
/// returning the resulting trait ref and all obligations that arise.
223+
/// The obligations are closed under normalization.
224+
pub fn inherent_impl_and_oblig<'a, 'tcx>(
225+
selcx: &mut SelectionContext<'a, 'tcx>,
226+
param_env: ty::ParamEnv<'tcx>,
227+
impl_def_id: DefId,
228+
impl_substs: SubstsRef<'tcx>,
229+
) -> (Ty<'tcx>, impl Iterator<Item = PredicateObligation<'tcx>>) {
230+
let ty = selcx.tcx().type_of(impl_def_id);
231+
let ty = ty.subst(selcx.tcx(), impl_substs);
232+
let Normalized { value: ty, obligations: normalization_obligations1 } =
233+
super::normalize(selcx, param_env, ObligationCause::dummy(), ty);
234+
235+
let predicates = selcx.tcx().predicates_of(impl_def_id);
236+
let predicates = predicates.instantiate(selcx.tcx(), impl_substs);
237+
let Normalized { value: predicates, obligations: normalization_obligations2 } =
238+
super::normalize(selcx, param_env, ObligationCause::dummy(), predicates);
239+
let impl_obligations =
240+
predicates_for_generics(ObligationCause::dummy(), 0, param_env, predicates);
241+
242+
let impl_obligations = impl_obligations
243+
.chain(normalization_obligations1.into_iter())
244+
.chain(normalization_obligations2.into_iter());
245+
246+
(ty, impl_obligations)
247+
}
248+
221249
pub fn predicates_for_generics<'tcx>(
222250
cause: ObligationCause<'tcx>,
223251
recursion_depth: usize,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// check-pass
2+
3+
#![feature(negative_impls)]
4+
#![feature(rustc_attrs)]
5+
#![feature(with_negative_coherence)]
6+
7+
trait Foo {}
8+
9+
impl !Foo for u32 {}
10+
11+
#[rustc_strict_coherence]
12+
struct MyStruct<T>(T);
13+
14+
impl MyStruct<u32> {
15+
fn method(&self) {}
16+
}
17+
18+
impl<T> MyStruct<T>
19+
where
20+
T: Foo,
21+
{
22+
fn method(&self) {}
23+
}
24+
25+
fn main() {}

0 commit comments

Comments
 (0)