Skip to content

Commit 5a59704

Browse files
committed
Auto merge of #46329 - arielb1:incoherent, r=eddyb
Revert "fix treatment of local types in "remote coherence" mode" That commit had accidentally snuck in into #44884 and it causes regressions. Revert it. This reverts commit c48650e. @bors p=10 - fixes breakage in nightly r? @eddyb
2 parents 3bde5e7 + bef4fe9 commit 5a59704

File tree

2 files changed

+48
-81
lines changed

2 files changed

+48
-81
lines changed

src/librustc/traits/coherence.rs

+46-79
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,8 @@ use ty::subst::Subst;
1919

2020
use infer::{InferCtxt, InferOk};
2121

22-
#[derive(Copy, Clone, Debug)]
23-
enum InferIsLocal {
24-
BrokenYes,
25-
Yes,
26-
No
27-
}
28-
29-
#[derive(Debug, Copy, Clone)]
30-
pub enum Conflict {
31-
Upstream,
32-
Downstream
33-
}
22+
#[derive(Copy, Clone)]
23+
struct InferIsLocal(bool);
3424

3525
pub struct OverlapResult<'tcx> {
3626
pub impl_header: ty::ImplHeader<'tcx>,
@@ -136,46 +126,32 @@ fn overlap<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>,
136126
}
137127

138128
pub fn trait_ref_is_knowable<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
139-
trait_ref: ty::TraitRef<'tcx>,
140-
broken: bool)
141-
-> Option<Conflict>
129+
trait_ref: ty::TraitRef<'tcx>) -> bool
142130
{
143-
debug!("trait_ref_is_knowable(trait_ref={:?}, broken={:?})", trait_ref, broken);
144-
let mode = if broken {
145-
InferIsLocal::BrokenYes
146-
} else {
147-
InferIsLocal::Yes
148-
};
149-
if orphan_check_trait_ref(tcx, trait_ref, mode).is_ok() {
150-
// A downstream or cousin crate is allowed to implement some
151-
// substitution of this trait-ref.
152-
debug!("trait_ref_is_knowable: downstream crate might implement");
153-
return Some(Conflict::Downstream);
154-
}
131+
debug!("trait_ref_is_knowable(trait_ref={:?})", trait_ref);
155132

156-
if trait_ref_is_local_or_fundamental(tcx, trait_ref) {
157-
// This is a local or fundamental trait, so future-compatibility
158-
// is no concern. We know that downstream/cousin crates are not
159-
// allowed to implement a substitution of this trait ref, which
160-
// means impls could only come from dependencies of this crate,
161-
// which we already know about.
162-
return None;
163-
}
164-
// This is a remote non-fundamental trait, so if another crate
165-
// can be the "final owner" of a substitution of this trait-ref,
166-
// they are allowed to implement it future-compatibly.
167-
//
168-
// However, if we are a final owner, then nobody else can be,
169-
// and if we are an intermediate owner, then we don't care
170-
// about future-compatibility, which means that we're OK if
171-
// we are an owner.
172-
if orphan_check_trait_ref(tcx, trait_ref, InferIsLocal::No).is_ok() {
133+
// if the orphan rules pass, that means that no ancestor crate can
134+
// impl this, so it's up to us.
135+
if orphan_check_trait_ref(tcx, trait_ref, InferIsLocal(false)).is_ok() {
173136
debug!("trait_ref_is_knowable: orphan check passed");
174-
return None;
175-
} else {
176-
debug!("trait_ref_is_knowable: nonlocal, nonfundamental, unowned");
177-
return Some(Conflict::Upstream);
137+
return true;
138+
}
139+
140+
// if the trait is not marked fundamental, then it's always possible that
141+
// an ancestor crate will impl this in the future, if they haven't
142+
// already
143+
if !trait_ref_is_local_or_fundamental(tcx, trait_ref) {
144+
debug!("trait_ref_is_knowable: trait is neither local nor fundamental");
145+
return false;
178146
}
147+
148+
// find out when some downstream (or cousin) crate could impl this
149+
// trait-ref, presuming that all the parameters were instantiated
150+
// with downstream types. If not, then it could only be
151+
// implemented by an upstream crate, which means that the impl
152+
// must be visible to us, and -- since the trait is fundamental
153+
// -- we can test.
154+
orphan_check_trait_ref(tcx, trait_ref, InferIsLocal(true)).is_err()
179155
}
180156

181157
pub fn trait_ref_is_local_or_fundamental<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
@@ -213,16 +189,16 @@ pub fn orphan_check<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
213189
return Ok(());
214190
}
215191

216-
orphan_check_trait_ref(tcx, trait_ref, InferIsLocal::No)
192+
orphan_check_trait_ref(tcx, trait_ref, InferIsLocal(false))
217193
}
218194

219195
fn orphan_check_trait_ref<'tcx>(tcx: TyCtxt,
220196
trait_ref: ty::TraitRef<'tcx>,
221197
infer_is_local: InferIsLocal)
222198
-> Result<(), OrphanCheckErr<'tcx>>
223199
{
224-
debug!("orphan_check_trait_ref(trait_ref={:?}, infer_is_local={:?})",
225-
trait_ref, infer_is_local);
200+
debug!("orphan_check_trait_ref(trait_ref={:?}, infer_is_local={})",
201+
trait_ref, infer_is_local.0);
226202

227203
// First, create an ordered iterator over all the type parameters to the trait, with the self
228204
// type appearing first.
@@ -236,9 +212,7 @@ fn orphan_check_trait_ref<'tcx>(tcx: TyCtxt,
236212
// uncovered type parameters.
237213
let uncovered_tys = uncovered_tys(tcx, input_ty, infer_is_local);
238214
for uncovered_ty in uncovered_tys {
239-
if let Some(param) = uncovered_ty.walk()
240-
.find(|t| is_possibly_remote_type(t, infer_is_local))
241-
{
215+
if let Some(param) = uncovered_ty.walk().find(|t| is_type_parameter(t)) {
242216
debug!("orphan_check_trait_ref: uncovered type `{:?}`", param);
243217
return Err(OrphanCheckErr::UncoveredTy(param));
244218
}
@@ -250,11 +224,11 @@ fn orphan_check_trait_ref<'tcx>(tcx: TyCtxt,
250224

251225
// Otherwise, enforce invariant that there are no type
252226
// parameters reachable.
253-
if let Some(param) = input_ty.walk()
254-
.find(|t| is_possibly_remote_type(t, infer_is_local))
255-
{
256-
debug!("orphan_check_trait_ref: uncovered type `{:?}`", param);
257-
return Err(OrphanCheckErr::UncoveredTy(param));
227+
if !infer_is_local.0 {
228+
if let Some(param) = input_ty.walk().find(|t| is_type_parameter(t)) {
229+
debug!("orphan_check_trait_ref: uncovered type `{:?}`", param);
230+
return Err(OrphanCheckErr::UncoveredTy(param));
231+
}
258232
}
259233
}
260234

@@ -276,7 +250,7 @@ fn uncovered_tys<'tcx>(tcx: TyCtxt, ty: Ty<'tcx>, infer_is_local: InferIsLocal)
276250
}
277251
}
278252

279-
fn is_possibly_remote_type(ty: Ty, _infer_is_local: InferIsLocal) -> bool {
253+
fn is_type_parameter(ty: Ty) -> bool {
280254
match ty.sty {
281255
ty::TyProjection(..) | ty::TyParam(..) => true,
282256
_ => false,
@@ -299,15 +273,7 @@ fn fundamental_ty(tcx: TyCtxt, ty: Ty) -> bool {
299273
}
300274
}
301275

302-
fn def_id_is_local(def_id: DefId, infer_is_local: InferIsLocal) -> bool {
303-
match infer_is_local {
304-
InferIsLocal::Yes => false,
305-
InferIsLocal::No |
306-
InferIsLocal::BrokenYes => def_id.is_local()
307-
}
308-
}
309-
310-
fn ty_is_local_constructor(ty: Ty, infer_is_local: InferIsLocal) -> bool {
276+
fn ty_is_local_constructor(ty: Ty, infer_is_local: InferIsLocal)-> bool {
311277
debug!("ty_is_local_constructor({:?})", ty);
312278

313279
match ty.sty {
@@ -330,19 +296,20 @@ fn ty_is_local_constructor(ty: Ty, infer_is_local: InferIsLocal) -> bool {
330296
false
331297
}
332298

333-
ty::TyInfer(..) => match infer_is_local {
334-
InferIsLocal::No => false,
335-
InferIsLocal::Yes |
336-
InferIsLocal::BrokenYes => true
337-
},
299+
ty::TyInfer(..) => {
300+
infer_is_local.0
301+
}
302+
303+
ty::TyAdt(def, _) => {
304+
def.did.is_local()
305+
}
338306

339-
ty::TyAdt(def, _) => def_id_is_local(def.did, infer_is_local),
340-
ty::TyForeign(did) => def_id_is_local(did, infer_is_local),
307+
ty::TyForeign(did) => {
308+
did.is_local()
309+
}
341310

342311
ty::TyDynamic(ref tt, ..) => {
343-
tt.principal().map_or(false, |p| {
344-
def_id_is_local(p.def_id(), infer_is_local)
345-
})
312+
tt.principal().map_or(false, |p| p.def_id().is_local())
346313
}
347314

348315
ty::TyError => {

src/librustc/traits/select.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -814,7 +814,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
814814
// terms of `Fn` etc, but we could probably make this more
815815
// precise still.
816816
let unbound_input_types = stack.fresh_trait_ref.input_types().any(|ty| ty.is_fresh());
817-
if unbound_input_types && self.intercrate && false {
817+
if unbound_input_types && self.intercrate {
818818
debug!("evaluate_stack({:?}) --> unbound argument, intercrate --> ambiguous",
819819
stack.fresh_trait_ref);
820820
// Heuristics: show the diagnostics when there are no candidates in crate.
@@ -1221,7 +1221,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
12211221
// bound regions
12221222
let trait_ref = predicate.skip_binder().trait_ref;
12231223

1224-
coherence::trait_ref_is_knowable(self.tcx(), trait_ref, false).is_none()
1224+
coherence::trait_ref_is_knowable(self.tcx(), trait_ref)
12251225
}
12261226

12271227
/// Returns true if the global caches can be used.

0 commit comments

Comments
 (0)