Skip to content

Commit 0fcabec

Browse files
authored
Rollup merge of #100888 - spastorino:coherence-negative-impls-implied-bounds, r=lcnr
Coherence negative impls implied bounds Fixes #93875 This PR is rebased on top of #100789 and it would need to include that one which is already r+ed. r? ``@nikomatsakis`` cc ``@lcnr`` (which I've talked about 3222f42, I guess after you finish your reordering of modules and work with OutlivesEnvironmentEnv this commit can just be reverted).
2 parents e802df9 + 4da14ef commit 0fcabec

File tree

10 files changed

+42
-33
lines changed

10 files changed

+42
-33
lines changed

compiler/rustc_trait_selection/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#![feature(let_else)]
2121
#![feature(if_let_guard)]
2222
#![feature(never_type)]
23+
#![feature(type_alias_impl_trait)]
2324
#![recursion_limit = "512"] // For rustdoc
2425

2526
#[macro_use]

compiler/rustc_trait_selection/src/traits/coherence.rs

+30-11
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,18 @@
66
77
use crate::infer::outlives::env::OutlivesEnvironment;
88
use crate::infer::{CombinedSnapshot, InferOk};
9+
use crate::traits::outlives_bounds::InferCtxtExt as _;
910
use crate::traits::select::IntercrateAmbiguityCause;
1011
use crate::traits::util::impl_subject_and_oblig;
1112
use crate::traits::SkipLeakCheck;
1213
use crate::traits::{
13-
self, Normalized, Obligation, ObligationCause, PredicateObligation, PredicateObligations,
14-
SelectionContext,
14+
self, Normalized, Obligation, ObligationCause, ObligationCtxt, PredicateObligation,
15+
PredicateObligations, SelectionContext,
1516
};
1617
use rustc_data_structures::fx::FxIndexSet;
1718
use rustc_errors::Diagnostic;
18-
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
19+
use rustc_hir::def_id::{DefId, CRATE_DEF_ID, LOCAL_CRATE};
20+
use rustc_hir::CRATE_HIR_ID;
1921
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
2022
use rustc_infer::traits::util;
2123
use rustc_middle::traits::specialization_graph::OverlapMode;
@@ -322,7 +324,7 @@ fn negative_impl<'cx, 'tcx>(
322324
let (subject2, obligations) =
323325
impl_subject_and_oblig(selcx, impl_env, impl2_def_id, impl2_substs);
324326

325-
!equate(&infcx, impl_env, subject1, subject2, obligations)
327+
!equate(&infcx, impl_env, subject1, subject2, obligations, impl1_def_id)
326328
})
327329
}
328330

@@ -332,6 +334,7 @@ fn equate<'cx, 'tcx>(
332334
subject1: ImplSubject<'tcx>,
333335
subject2: ImplSubject<'tcx>,
334336
obligations: impl Iterator<Item = PredicateObligation<'tcx>>,
337+
body_def_id: DefId,
335338
) -> bool {
336339
// do the impls unify? If not, not disjoint.
337340
let Ok(InferOk { obligations: more_obligations, .. }) =
@@ -342,8 +345,10 @@ fn equate<'cx, 'tcx>(
342345
};
343346

344347
let selcx = &mut SelectionContext::new(&infcx);
345-
let opt_failing_obligation =
346-
obligations.into_iter().chain(more_obligations).find(|o| negative_impl_exists(selcx, o));
348+
let opt_failing_obligation = obligations
349+
.into_iter()
350+
.chain(more_obligations)
351+
.find(|o| negative_impl_exists(selcx, o, body_def_id));
347352

348353
if let Some(failing_obligation) = opt_failing_obligation {
349354
debug!("overlap: obligation unsatisfiable {:?}", failing_obligation);
@@ -358,14 +363,15 @@ fn equate<'cx, 'tcx>(
358363
fn negative_impl_exists<'cx, 'tcx>(
359364
selcx: &SelectionContext<'cx, 'tcx>,
360365
o: &PredicateObligation<'tcx>,
366+
body_def_id: DefId,
361367
) -> bool {
362-
if resolve_negative_obligation(selcx.infcx().fork(), o) {
368+
if resolve_negative_obligation(selcx.infcx().fork(), o, body_def_id) {
363369
return true;
364370
}
365371

366372
// Try to prove a negative obligation exists for super predicates
367373
for o in util::elaborate_predicates(selcx.tcx(), iter::once(o.predicate)) {
368-
if resolve_negative_obligation(selcx.infcx().fork(), &o) {
374+
if resolve_negative_obligation(selcx.infcx().fork(), &o, body_def_id) {
369375
return true;
370376
}
371377
}
@@ -377,6 +383,7 @@ fn negative_impl_exists<'cx, 'tcx>(
377383
fn resolve_negative_obligation<'cx, 'tcx>(
378384
infcx: InferCtxt<'cx, 'tcx>,
379385
o: &PredicateObligation<'tcx>,
386+
body_def_id: DefId,
380387
) -> bool {
381388
let tcx = infcx.tcx;
382389

@@ -385,12 +392,24 @@ fn resolve_negative_obligation<'cx, 'tcx>(
385392
};
386393

387394
let param_env = o.param_env;
388-
let errors = super::fully_solve_obligation(&infcx, o);
389-
if !errors.is_empty() {
395+
if !super::fully_solve_obligation(&infcx, o).is_empty() {
390396
return false;
391397
}
392398

393-
let outlives_env = OutlivesEnvironment::new(param_env);
399+
let (body_id, body_def_id) = if let Some(body_def_id) = body_def_id.as_local() {
400+
(tcx.hir().local_def_id_to_hir_id(body_def_id), body_def_id)
401+
} else {
402+
(CRATE_HIR_ID, CRATE_DEF_ID)
403+
};
404+
405+
let ocx = ObligationCtxt::new(&infcx);
406+
let wf_tys = ocx.assumed_wf_types(param_env, DUMMY_SP, body_def_id);
407+
let outlives_env = OutlivesEnvironment::with_bounds(
408+
param_env,
409+
Some(&infcx),
410+
infcx.implied_bounds_tys(param_env, body_id, wf_tys),
411+
);
412+
394413
infcx.process_registered_region_obligations(outlives_env.region_bound_pairs(), param_env);
395414

396415
infcx.resolve_regions(&outlives_env).is_empty()

compiler/rustc_trait_selection/src/traits/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ mod fulfill;
1313
pub mod misc;
1414
mod object_safety;
1515
mod on_unimplemented;
16+
pub mod outlives_bounds;
1617
mod project;
1718
pub mod query;
1819
pub(crate) mod relationships;

compiler/rustc_typeck/src/outlives/outlives_bounds.rs renamed to compiler/rustc_trait_selection/src/traits/outlives_bounds.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1+
use crate::infer::InferCtxt;
2+
use crate::traits::query::type_op::{self, TypeOp, TypeOpOutput};
3+
use crate::traits::query::NoSolution;
4+
use crate::traits::{ObligationCause, TraitEngine, TraitEngineExt};
15
use rustc_data_structures::fx::FxHashSet;
26
use rustc_hir as hir;
37
use rustc_hir::HirId;
48
use rustc_middle::ty::{self, ParamEnv, Ty};
5-
use rustc_trait_selection::infer::InferCtxt;
6-
use rustc_trait_selection::traits::query::type_op::{self, TypeOp, TypeOpOutput};
7-
use rustc_trait_selection::traits::query::NoSolution;
8-
use rustc_trait_selection::traits::{ObligationCause, TraitEngine, TraitEngineExt};
99

1010
pub use rustc_middle::traits::query::OutlivesBound;
1111

compiler/rustc_typeck/src/check/compare_method.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use super::potentially_plural_count;
22
use crate::errors::LifetimesOrBoundsMismatchOnTrait;
3-
use crate::outlives::outlives_bounds::InferCtxtExt as _;
43
use rustc_data_structures::fx::FxHashSet;
54
use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId, ErrorGuaranteed};
65
use rustc_hir as hir;
@@ -17,6 +16,7 @@ use rustc_middle::ty::{self, DefIdTree};
1716
use rustc_middle::ty::{GenericParamDefKind, ToPredicate, TyCtxt};
1817
use rustc_span::Span;
1918
use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
19+
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
2020
use rustc_trait_selection::traits::{
2121
self, ObligationCause, ObligationCauseCode, ObligationCtxt, Reveal,
2222
};

compiler/rustc_typeck/src/check/wfcheck.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter};
2-
use crate::outlives::outlives_bounds::InferCtxtExt as _;
32
use rustc_ast as ast;
43
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
54
use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed};
@@ -22,6 +21,7 @@ use rustc_span::symbol::{sym, Ident, Symbol};
2221
use rustc_span::{Span, DUMMY_SP};
2322
use rustc_trait_selection::autoderef::Autoderef;
2423
use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
24+
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
2525
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
2626
use rustc_trait_selection::traits::{
2727
self, ObligationCause, ObligationCauseCode, ObligationCtxt, WellFormedLoc,

compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@
6767
6868
use crate::constrained_generic_params as cgp;
6969
use crate::errors::SubstsOnOverriddenImpl;
70-
use crate::outlives::outlives_bounds::InferCtxtExt as _;
7170

7271
use rustc_data_structures::fx::FxHashSet;
7372
use rustc_hir::def_id::{DefId, LocalDefId};
@@ -79,6 +78,7 @@ use rustc_middle::ty::trait_def::TraitSpecializationKind;
7978
use rustc_middle::ty::{self, TyCtxt, TypeVisitable};
8079
use rustc_span::Span;
8180
use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
81+
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
8282
use rustc_trait_selection::traits::{self, translate_substs, wf, ObligationCtxt};
8383

8484
pub(super) fn check_min_specialization(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) {

compiler/rustc_typeck/src/outlives/mod.rs

-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ use rustc_span::Span;
99

1010
mod explicit;
1111
mod implicit_infer;
12-
pub(crate) mod outlives_bounds;
1312
/// Code to write unit test for outlives.
1413
pub mod test;
1514
mod utils;
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
// revisions: stock with_negative_coherence
2+
//[with_negative_coherence] check-pass
3+
24
#![feature(negative_impls)]
35
#![cfg_attr(with_negative_coherence, feature(with_negative_coherence))]
46

5-
// FIXME: this should compile
6-
77
trait MyPredicate<'a> {}
88

99
impl<'a, T> !MyPredicate<'a> for &'a T where T: 'a {}
@@ -12,6 +12,6 @@ trait MyTrait<'a> {}
1212

1313
impl<'a, T: MyPredicate<'a>> MyTrait<'a> for T {}
1414
impl<'a, T> MyTrait<'a> for &'a T {}
15-
//~^ ERROR: conflicting implementations of trait `MyTrait<'_>` for type `&_`
15+
//[stock]~^ ERROR: conflicting implementations of trait `MyTrait<'_>` for type `&_`
1616

1717
fn main() {}

src/test/ui/coherence/coherence-negative-outlives-lifetimes.with_negative_coherence.stderr

-11
This file was deleted.

0 commit comments

Comments
 (0)