From d96faef9138d6618e36fec1919e1c9305fefa96c Mon Sep 17 00:00:00 2001 From: Santiago Pastorino <spastorino@gmail.com> Date: Thu, 24 Mar 2022 17:47:10 -0300 Subject: [PATCH] Where bounds are checked on inherent impls --- .../src/traits/coherence.rs | 10 +++++-- .../rustc_trait_selection/src/traits/util.rs | 28 +++++++++++++++++++ ...oherence-negative-inherent-where-bounds.rs | 25 +++++++++++++++++ 3 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/coherence/coherence-negative-inherent-where-bounds.rs diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index f3385df513f..ed9ddb51834 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -7,7 +7,7 @@ use crate::infer::outlives::env::OutlivesEnvironment; use crate::infer::{CombinedSnapshot, InferOk, RegionckMode}; use crate::traits::select::IntercrateAmbiguityCause; -use crate::traits::util::impl_trait_ref_and_oblig; +use crate::traits::util::{impl_trait_ref_and_oblig, inherent_impl_and_oblig}; use crate::traits::SkipLeakCheck; use crate::traits::{ self, FulfillmentContext, Normalized, Obligation, ObligationCause, PredicateObligation, @@ -338,7 +338,13 @@ fn impl_subject_and_obligations<'cx, 'tcx>( (ImplSubject::Trait(impl2_trait_ref), Box::new(obligations)) } else { - (infcx.tcx.impl_subject(impl2_def_id), Box::new(iter::empty())) + // Attempt to prove that impl2 applies, given all of the above. + let selcx = &mut SelectionContext::new(&infcx); + let impl2_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl2_def_id); + let (impl2_ty, obligations) = + inherent_impl_and_oblig(selcx, impl_env, impl2_def_id, impl2_substs); + + (ImplSubject::Inherent(impl2_ty), Box::new(obligations)) } } diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index f800e7a1402..7b64deac99d 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -218,6 +218,34 @@ pub fn impl_trait_ref_and_oblig<'a, 'tcx>( (impl_trait_ref, impl_obligations) } +/// Instantiate all bound parameters of the impl with the given substs, +/// returning the resulting trait ref and all obligations that arise. +/// The obligations are closed under normalization. +pub fn inherent_impl_and_oblig<'a, 'tcx>( + selcx: &mut SelectionContext<'a, 'tcx>, + param_env: ty::ParamEnv<'tcx>, + impl_def_id: DefId, + impl_substs: SubstsRef<'tcx>, +) -> (Ty<'tcx>, impl Iterator<Item = PredicateObligation<'tcx>>) { + let ty = selcx.tcx().type_of(impl_def_id); + let ty = ty.subst(selcx.tcx(), impl_substs); + let Normalized { value: ty, obligations: normalization_obligations1 } = + super::normalize(selcx, param_env, ObligationCause::dummy(), ty); + + let predicates = selcx.tcx().predicates_of(impl_def_id); + let predicates = predicates.instantiate(selcx.tcx(), impl_substs); + let Normalized { value: predicates, obligations: normalization_obligations2 } = + super::normalize(selcx, param_env, ObligationCause::dummy(), predicates); + let impl_obligations = + predicates_for_generics(ObligationCause::dummy(), 0, param_env, predicates); + + let impl_obligations = impl_obligations + .chain(normalization_obligations1.into_iter()) + .chain(normalization_obligations2.into_iter()); + + (ty, impl_obligations) +} + pub fn predicates_for_generics<'tcx>( cause: ObligationCause<'tcx>, recursion_depth: usize, diff --git a/src/test/ui/coherence/coherence-negative-inherent-where-bounds.rs b/src/test/ui/coherence/coherence-negative-inherent-where-bounds.rs new file mode 100644 index 00000000000..39ccaa6ac35 --- /dev/null +++ b/src/test/ui/coherence/coherence-negative-inherent-where-bounds.rs @@ -0,0 +1,25 @@ +// check-pass + +#![feature(negative_impls)] +#![feature(rustc_attrs)] +#![feature(with_negative_coherence)] + +trait Foo {} + +impl !Foo for u32 {} + +#[rustc_strict_coherence] +struct MyStruct<T>(T); + +impl MyStruct<u32> { + fn method(&self) {} +} + +impl<T> MyStruct<T> +where + T: Foo, +{ + fn method(&self) {} +} + +fn main() {}