about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSantiago Pastorino <spastorino@gmail.com>2022-02-02 14:36:45 -0300
committerSantiago Pastorino <spastorino@gmail.com>2022-02-14 12:56:28 -0300
commit3fd89a662a8360bbcd64da1353be8bf3b8833af5 (patch)
tree722f54f813941e78cc842c9fa60e3bff79c2db97
parentb61e1bbf06334e235e475652bb41a603584e7150 (diff)
downloadrust-3fd89a662a8360bbcd64da1353be8bf3b8833af5.tar.gz
rust-3fd89a662a8360bbcd64da1353be8bf3b8833af5.zip
Properly check regions on negative overlap check
-rw-r--r--compiler/rustc_trait_selection/src/traits/coherence.rs42
-rw-r--r--src/test/ui/coherence/auxiliary/error_lib.rs1
-rw-r--r--src/test/ui/coherence/coherence-overlap-negate-use-feature-gate.rs2
-rw-r--r--src/test/ui/coherence/coherence-overlap-negative-trait.rs2
-rw-r--r--src/test/ui/coherence/coherence-overlap-with-regions.rs16
-rw-r--r--src/test/ui/traits/negative-impls/auxiliary/foreign_trait.rs1
-rw-r--r--src/test/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.rs9
7 files changed, 59 insertions, 14 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs
index dd1293f1def..8ee578b77dc 100644
--- a/compiler/rustc_trait_selection/src/traits/coherence.rs
+++ b/compiler/rustc_trait_selection/src/traits/coherence.rs
@@ -4,8 +4,8 @@
 //! [trait-resolution]: https://rustc-dev-guide.rust-lang.org/traits/resolution.html
 //! [trait-specialization]: https://rustc-dev-guide.rust-lang.org/traits/specialization.html
 
-use crate::infer::{CombinedSnapshot, InferOk, TyCtxtInferExt};
-use crate::traits::query::evaluate_obligation::InferCtxtExt;
+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::SkipLeakCheck;
@@ -13,7 +13,11 @@ use crate::traits::{
     self, FulfillmentContext, Normalized, Obligation, ObligationCause, PredicateObligation,
     PredicateObligations, SelectionContext,
 };
+//use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
+use rustc_hir::CRATE_HIR_ID;
+use rustc_infer::infer::TyCtxtInferExt;
+use rustc_infer::traits::TraitEngine;
 use rustc_middle::traits::specialization_graph::OverlapMode;
 use rustc_middle::ty::fast_reject::{self, SimplifyParams, StripReferences};
 use rustc_middle::ty::fold::TypeFoldable;
@@ -270,7 +274,6 @@ fn implicit_negative<'cx, 'tcx>(
         impl1_header, impl2_header, obligations
     );
     let infcx = selcx.infcx();
-    let tcx = infcx.tcx;
     let opt_failing_obligation = impl1_header
         .predicates
         .iter()
@@ -349,7 +352,7 @@ fn negative_impl<'cx, 'tcx>(
         let opt_failing_obligation = obligations
             .into_iter()
             .chain(more_obligations)
-            .find(|o| negative_impl_exists(selcx, o));
+            .find(|o| negative_impl_exists(selcx, impl1_env, impl1_def_id, o));
 
         if let Some(failing_obligation) = opt_failing_obligation {
             debug!("overlap: obligation unsatisfiable {:?}", failing_obligation);
@@ -372,15 +375,38 @@ fn loose_check<'cx, 'tcx>(
 
 fn negative_impl_exists<'cx, 'tcx>(
     selcx: &SelectionContext<'cx, 'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    region_context: DefId,
     o: &PredicateObligation<'tcx>,
 ) -> bool {
-    let infcx = selcx.infcx();
+    let infcx = selcx.infcx().clone();
     let tcx = infcx.tcx;
     o.flip_polarity(tcx)
-        .as_ref()
         .map(|o| {
-            // FIXME This isn't quite correct, regions should be included
-            selcx.infcx().predicate_must_hold_modulo_regions(o)
+            let mut fulfillment_cx = FulfillmentContext::new();
+            fulfillment_cx.register_predicate_obligation(infcx, o);
+
+            let errors = fulfillment_cx.select_all_or_error(infcx);
+            if !errors.is_empty() {
+                return false;
+            }
+
+            let mut outlives_env = OutlivesEnvironment::new(param_env);
+            outlives_env.save_implied_bounds(CRATE_HIR_ID);
+
+            infcx.process_registered_region_obligations(
+                outlives_env.region_bound_pairs_map(),
+                Some(tcx.lifetimes.re_root_empty),
+                param_env,
+            );
+
+            let errors =
+                infcx.resolve_regions(region_context, &outlives_env, RegionckMode::default());
+            if !errors.is_empty() {
+                return false;
+            }
+
+            true
         })
         .unwrap_or(false)
 }
diff --git a/src/test/ui/coherence/auxiliary/error_lib.rs b/src/test/ui/coherence/auxiliary/error_lib.rs
index 43806cb995c..19ff9ae62fd 100644
--- a/src/test/ui/coherence/auxiliary/error_lib.rs
+++ b/src/test/ui/coherence/auxiliary/error_lib.rs
@@ -1,5 +1,6 @@
 #![crate_type = "lib"]
 #![feature(negative_impls)]
+#![feature(with_negative_coherence)]
 
 pub trait Error {}
 impl !Error for &str {}
diff --git a/src/test/ui/coherence/coherence-overlap-negate-use-feature-gate.rs b/src/test/ui/coherence/coherence-overlap-negate-use-feature-gate.rs
index e024eae9819..a0dd881d1aa 100644
--- a/src/test/ui/coherence/coherence-overlap-negate-use-feature-gate.rs
+++ b/src/test/ui/coherence/coherence-overlap-negate-use-feature-gate.rs
@@ -1,6 +1,6 @@
 // check-pass
 
-#![feature(negative_impls)]
+#![feature(with_negative_coherence)]
 
 use std::ops::DerefMut;
 
diff --git a/src/test/ui/coherence/coherence-overlap-negative-trait.rs b/src/test/ui/coherence/coherence-overlap-negative-trait.rs
index ab65163bea4..8059d23ffd2 100644
--- a/src/test/ui/coherence/coherence-overlap-negative-trait.rs
+++ b/src/test/ui/coherence/coherence-overlap-negative-trait.rs
@@ -3,7 +3,7 @@
 //
 // Check that if we promise to not impl what would overlap it doesn't actually overlap
 
-#![feature(negative_impls)]
+#![feature(with_negative_coherence)]
 
 extern crate error_lib as lib;
 use lib::Error;
diff --git a/src/test/ui/coherence/coherence-overlap-with-regions.rs b/src/test/ui/coherence/coherence-overlap-with-regions.rs
new file mode 100644
index 00000000000..32f01f41801
--- /dev/null
+++ b/src/test/ui/coherence/coherence-overlap-with-regions.rs
@@ -0,0 +1,16 @@
+// check-pass
+
+#![feature(negative_impls)]
+#![feature(rustc_attrs)]
+#![feature(with_negative_coherence)]
+
+#[rustc_strict_coherence]
+trait Foo {}
+impl<T> !Foo for &T where T: 'static {}
+
+#[rustc_strict_coherence]
+trait Bar {}
+impl<T: Foo> Bar for T {}
+impl<T> Bar for &T where T: 'static {}
+
+fn main() {}
diff --git a/src/test/ui/traits/negative-impls/auxiliary/foreign_trait.rs b/src/test/ui/traits/negative-impls/auxiliary/foreign_trait.rs
index 681f26438e6..0e17f089048 100644
--- a/src/test/ui/traits/negative-impls/auxiliary/foreign_trait.rs
+++ b/src/test/ui/traits/negative-impls/auxiliary/foreign_trait.rs
@@ -1,4 +1,5 @@
 #![feature(negative_impls)]
+#![feature(with_negative_coherence)]
 
 pub trait ForeignTrait {}
 
diff --git a/src/test/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.rs b/src/test/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.rs
index 119ac05c33e..c1f96ab8c14 100644
--- a/src/test/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.rs
+++ b/src/test/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.rs
@@ -1,6 +1,7 @@
 // check-pass
 
 #![feature(negative_impls)]
+#![feature(with_negative_coherence)]
 
 // aux-build: foreign_trait.rs
 
@@ -16,8 +17,8 @@
 extern crate foreign_trait;
 use foreign_trait::ForeignTrait;
 
-trait LocalTrait { }
-impl<T: ForeignTrait> LocalTrait for T { }
-impl LocalTrait for String { }
+trait LocalTrait {}
+impl<T: ForeignTrait> LocalTrait for T {}
+impl LocalTrait for String {}
 
-fn main() { }
+fn main() {}