Skip to content

Commit 42f1f54

Browse files
committed
Don't treat closures from other crates as local
1 parent 4817259 commit 42f1f54

File tree

5 files changed

+58
-24
lines changed

5 files changed

+58
-24
lines changed

compiler/rustc_trait_selection/src/traits/coherence.rs

+20-22
Original file line numberDiff line numberDiff line change
@@ -401,12 +401,12 @@ fn resolve_negative_obligation<'tcx>(
401401
infcx.resolve_regions(&outlives_env).is_empty()
402402
}
403403

404+
#[instrument(level = "debug", skip(tcx), ret)]
404405
pub fn trait_ref_is_knowable<'tcx>(
405406
tcx: TyCtxt<'tcx>,
406407
trait_ref: ty::TraitRef<'tcx>,
407408
) -> Result<(), Conflict> {
408-
debug!("trait_ref_is_knowable(trait_ref={:?})", trait_ref);
409-
if orphan_check_trait_ref(tcx, trait_ref, InCrate::Remote).is_ok() {
409+
if orphan_check_trait_ref(trait_ref, InCrate::Remote).is_ok() {
410410
// A downstream or cousin crate is allowed to implement some
411411
// substitution of this trait-ref.
412412
return Err(Conflict::Downstream);
@@ -429,11 +429,9 @@ pub fn trait_ref_is_knowable<'tcx>(
429429
// and if we are an intermediate owner, then we don't care
430430
// about future-compatibility, which means that we're OK if
431431
// we are an owner.
432-
if orphan_check_trait_ref(tcx, trait_ref, InCrate::Local).is_ok() {
433-
debug!("trait_ref_is_knowable: orphan check passed");
432+
if orphan_check_trait_ref(trait_ref, InCrate::Local).is_ok() {
434433
Ok(())
435434
} else {
436-
debug!("trait_ref_is_knowable: nonlocal, nonfundamental, unowned");
437435
Err(Conflict::Upstream)
438436
}
439437
}
@@ -445,6 +443,7 @@ pub fn trait_ref_is_local_or_fundamental<'tcx>(
445443
trait_ref.def_id.krate == LOCAL_CRATE || tcx.has_attr(trait_ref.def_id, sym::fundamental)
446444
}
447445

446+
#[derive(Debug)]
448447
pub enum OrphanCheckErr<'tcx> {
449448
NonLocalInputType(Vec<(Ty<'tcx>, bool /* Is this the first input type? */)>),
450449
UncoveredTy(Ty<'tcx>, Option<Ty<'tcx>>),
@@ -456,21 +455,20 @@ pub enum OrphanCheckErr<'tcx> {
456455
///
457456
/// 1. All type parameters in `Self` must be "covered" by some local type constructor.
458457
/// 2. Some local type must appear in `Self`.
458+
#[instrument(level = "debug", skip(tcx), ret)]
459459
pub fn orphan_check(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Result<(), OrphanCheckErr<'_>> {
460-
debug!("orphan_check({:?})", impl_def_id);
461-
462460
// We only except this routine to be invoked on implementations
463461
// of a trait, not inherent implementations.
464462
let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().subst_identity();
465-
debug!("orphan_check: trait_ref={:?}", trait_ref);
463+
debug!(?trait_ref);
466464

467465
// If the *trait* is local to the crate, ok.
468466
if trait_ref.def_id.is_local() {
469467
debug!("trait {:?} is local to current crate", trait_ref.def_id);
470468
return Ok(());
471469
}
472470

473-
orphan_check_trait_ref(tcx, trait_ref, InCrate::Local)
471+
orphan_check_trait_ref(trait_ref, InCrate::Local)
474472
}
475473

476474
/// Checks whether a trait-ref is potentially implementable by a crate.
@@ -559,21 +557,19 @@ pub fn orphan_check(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Result<(), OrphanChe
559557
///
560558
/// Note that this function is never called for types that have both type
561559
/// parameters and inference variables.
560+
#[instrument(level = "trace", ret)]
562561
fn orphan_check_trait_ref<'tcx>(
563-
tcx: TyCtxt<'tcx>,
564562
trait_ref: ty::TraitRef<'tcx>,
565563
in_crate: InCrate,
566564
) -> Result<(), OrphanCheckErr<'tcx>> {
567-
debug!("orphan_check_trait_ref(trait_ref={:?}, in_crate={:?})", trait_ref, in_crate);
568-
569565
if trait_ref.needs_infer() && trait_ref.needs_subst() {
570566
bug!(
571567
"can't orphan check a trait ref with both params and inference variables {:?}",
572568
trait_ref
573569
);
574570
}
575571

576-
let mut checker = OrphanChecker::new(tcx, in_crate);
572+
let mut checker = OrphanChecker::new(in_crate);
577573
match trait_ref.visit_with(&mut checker) {
578574
ControlFlow::Continue(()) => Err(OrphanCheckErr::NonLocalInputType(checker.non_local_tys)),
579575
ControlFlow::Break(OrphanCheckEarlyExit::ParamTy(ty)) => {
@@ -592,7 +588,6 @@ fn orphan_check_trait_ref<'tcx>(
592588
}
593589

594590
struct OrphanChecker<'tcx> {
595-
tcx: TyCtxt<'tcx>,
596591
in_crate: InCrate,
597592
in_self_ty: bool,
598593
/// Ignore orphan check failures and exclusively search for the first
@@ -602,9 +597,8 @@ struct OrphanChecker<'tcx> {
602597
}
603598

604599
impl<'tcx> OrphanChecker<'tcx> {
605-
fn new(tcx: TyCtxt<'tcx>, in_crate: InCrate) -> Self {
600+
fn new(in_crate: InCrate) -> Self {
606601
OrphanChecker {
607-
tcx,
608602
in_crate,
609603
in_self_ty: true,
610604
search_first_local_ty: false,
@@ -697,13 +691,17 @@ impl<'tcx> TypeVisitor<'tcx> for OrphanChecker<'tcx> {
697691
}
698692
}
699693
ty::Error(_) => ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(ty)),
700-
ty::Closure(..) | ty::Generator(..) | ty::GeneratorWitness(..) => {
701-
self.tcx.sess.delay_span_bug(
702-
DUMMY_SP,
703-
format!("ty_is_local invoked on closure or generator: {:?}", ty),
704-
);
705-
ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(ty))
694+
ty::Closure(did, ..) | ty::Generator(did, ..) => {
695+
if self.def_id_is_local(did) {
696+
ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(ty))
697+
} else {
698+
self.found_non_local_ty(ty)
699+
}
706700
}
701+
// This should only be created when checking whether we have to check whether some
702+
// auto trait impl applies. There will never be multiple impls, so we can just
703+
// act as if it were a local type here.
704+
ty::GeneratorWitness(_) => ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(ty)),
707705
ty::Alias(ty::Opaque, ..) => {
708706
// This merits some explanation.
709707
// Normally, opaque types are not involved when performing

tests/ui/coherence/coherence-with-generator.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
// Test that encountering closures during coherence does not cause issues.
22
#![feature(type_alias_impl_trait, generators)]
3+
#![cfg_attr(specialized, feature(specialization))]
4+
#![allow(incomplete_features)]
5+
6+
// revisions: stock specialized
7+
// [specialized]check-pass
8+
39
type OpaqueGenerator = impl Sized;
410
fn defining_use() -> OpaqueGenerator {
511
|| {
@@ -13,6 +19,6 @@ struct Wrapper<T>(T);
1319
trait Trait {}
1420
impl Trait for Wrapper<OpaqueGenerator> {}
1521
impl<T: Sync> Trait for Wrapper<T> {}
16-
//~^ ERROR conflicting implementations of trait `Trait` for type `Wrapper<OpaqueGenerator>`
22+
//[stock]~^ ERROR conflicting implementations of trait `Trait` for type `Wrapper<OpaqueGenerator>`
1723

1824
fn main() {}

tests/ui/coherence/coherence-with-generator.stderr renamed to tests/ui/coherence/coherence-with-generator.stock.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0119]: conflicting implementations of trait `Trait` for type `Wrapper<OpaqueGenerator>`
2-
--> $DIR/coherence-with-generator.rs:15:1
2+
--> $DIR/coherence-with-generator.rs:21:1
33
|
44
LL | impl Trait for Wrapper<OpaqueGenerator> {}
55
| --------------------------------------- first implementation here
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#![feature(type_alias_impl_trait)]
2+
#![cfg_attr(specialized, feature(specialization))]
3+
#![allow(incomplete_features)]
4+
5+
// revisions: stock specialized
6+
// [specialized]check-pass
7+
8+
trait OpaqueTrait {}
9+
impl<T> OpaqueTrait for T {}
10+
type OpaqueType = impl OpaqueTrait;
11+
fn mk_opaque() -> OpaqueType {
12+
|| 0
13+
}
14+
trait AnotherTrait {}
15+
impl<T: Send> AnotherTrait for T {}
16+
impl AnotherTrait for OpaqueType {}
17+
//[stock]~^ conflicting implementations of trait `AnotherTrait` for type `OpaqueType`
18+
19+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error[E0119]: conflicting implementations of trait `AnotherTrait` for type `OpaqueType`
2+
--> $DIR/issue-104817.rs:16:1
3+
|
4+
LL | impl<T: Send> AnotherTrait for T {}
5+
| -------------------------------- first implementation here
6+
LL | impl AnotherTrait for OpaqueType {}
7+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `OpaqueType`
8+
9+
error: aborting due to previous error
10+
11+
For more information about this error, try `rustc --explain E0119`.

0 commit comments

Comments
 (0)