Skip to content

Commit 79fcaf8

Browse files
committed
Apply proper commit from PR #63934
While working on PR #63934, I accidentally reverted to an older version of the PR while working on a rebase. The PR was then merged, not with the later, approved changes, but with earlier, unapproved changes. This PR applies the changes that were *suppoesd* to be mereged in PR #63934. All of the proper tests appear to have been merged in PR #63934, so this PR adds no new tests Fixes #66580
1 parent b9cf541 commit 79fcaf8

File tree

2 files changed

+52
-15
lines changed

2 files changed

+52
-15
lines changed

src/librustc/traits/coherence.rs

+33-15
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,7 @@ fn orphan_check_trait_ref<'tcx>(
382382
ty: Ty<'tcx>,
383383
in_crate: InCrate,
384384
) -> Vec<Ty<'tcx>> {
385-
if fundamental_ty(ty) && ty_is_non_local(tcx, ty, in_crate).is_some() {
385+
if fundamental_ty(ty) && ty_is_non_local(ty, in_crate).is_some() {
386386
ty.walk_shallow().flat_map(|ty| uncover_fundamental_ty(tcx, ty, in_crate)).collect()
387387
} else {
388388
vec![ty]
@@ -396,7 +396,7 @@ fn orphan_check_trait_ref<'tcx>(
396396
.enumerate()
397397
{
398398
debug!("orphan_check_trait_ref: check ty `{:?}`", input_ty);
399-
let non_local_tys = ty_is_non_local(tcx, input_ty, in_crate);
399+
let non_local_tys = ty_is_non_local(input_ty, in_crate);
400400
if non_local_tys.is_none() {
401401
debug!("orphan_check_trait_ref: ty_is_local `{:?}`", input_ty);
402402
return Ok(());
@@ -405,7 +405,7 @@ fn orphan_check_trait_ref<'tcx>(
405405
let local_type = trait_ref
406406
.input_types()
407407
.flat_map(|ty| uncover_fundamental_ty(tcx, ty, in_crate))
408-
.filter(|ty| ty_is_non_local_constructor(tcx, ty, in_crate).is_none())
408+
.filter(|ty| ty_is_non_local_constructor(ty, in_crate).is_none())
409409
.next();
410410

411411
debug!("orphan_check_trait_ref: uncovered ty local_type: `{:?}`", local_type);
@@ -423,13 +423,13 @@ fn orphan_check_trait_ref<'tcx>(
423423
Err(OrphanCheckErr::NonLocalInputType(non_local_spans))
424424
}
425425

426-
fn ty_is_non_local<'t>(tcx: TyCtxt<'t>, ty: Ty<'t>, in_crate: InCrate) -> Option<Vec<Ty<'t>>> {
427-
match ty_is_non_local_constructor(tcx, ty, in_crate) {
426+
fn ty_is_non_local<'t>(ty: Ty<'t>, in_crate: InCrate) -> Option<Vec<Ty<'t>>> {
427+
match ty_is_non_local_constructor(ty, in_crate) {
428428
Some(ty) => if !fundamental_ty(ty) {
429429
Some(vec![ty])
430430
} else {
431431
let tys: Vec<_> = ty.walk_shallow()
432-
.filter_map(|t| ty_is_non_local(tcx, t, in_crate))
432+
.filter_map(|t| ty_is_non_local(t, in_crate))
433433
.flat_map(|i| i)
434434
.collect();
435435
if tys.is_empty() {
@@ -460,7 +460,6 @@ fn def_id_is_local(def_id: DefId, in_crate: InCrate) -> bool {
460460
}
461461

462462
fn ty_is_non_local_constructor<'tcx>(
463-
tcx: TyCtxt<'tcx>,
464463
ty: Ty<'tcx>,
465464
in_crate: InCrate,
466465
) -> Option<Ty<'tcx>> {
@@ -503,14 +502,33 @@ fn ty_is_non_local_constructor<'tcx>(
503502
} else {
504503
Some(ty)
505504
},
506-
ty::Opaque(did, _) => {
507-
// Check the underlying type that this opaque
508-
// type resolves to.
509-
// This recursion will eventually terminate,
510-
// since we've already managed to successfully
511-
// resolve all opaque types by this point
512-
let real_ty = tcx.type_of(did);
513-
ty_is_non_local_constructor(tcx, real_ty, in_crate)
505+
ty::Opaque(..) => {
506+
// This merits some explanation.
507+
// Normally, opaque types are not involed when performing
508+
// coherence checking, since it is illegal to directly
509+
// implement a trait on an opaque type. However, we might
510+
// end up looking at an opaque type during coherence checking
511+
// if an opaque type gets used within another type (e.g. as
512+
// a type parameter). This requires us to decide whether or
513+
// not an opaque type should be considered 'local' or not.
514+
//
515+
// We choose to treat all opaque types as non-local, even
516+
// those that appear within the same crate. This seems
517+
// somewhat suprising at first, but makes sense when
518+
// you consider that opaque types are supposed to hide
519+
// the underlying type *within the same crate*. When an
520+
// opaque type is used from outside the module
521+
// where it is declared, it should be impossible to observe
522+
// anyything about it other than the traits that it implements.
523+
//
524+
// The alternative would be to look at the underlying type
525+
// to determine whether or not the opaque type itself should
526+
// be considered local. However, this could make it a breaking change
527+
// to switch the underlying ('defining') type from a local type
528+
// to a remote type. This would violate the rule that opaque
529+
// types should be completely opaque apart from the traits
530+
// that they implement, so we don't use this behavior.
531+
Some(ty)
514532
}
515533

516534
ty::Dynamic(ref tt, ..) => {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Regression test for issue #66580
2+
// Ensures that we don't try to determine whether a closure
3+
// is foreign when it's the underlying type of an opaque type
4+
// check-pass
5+
#![feature(type_alias_impl_trait)]
6+
7+
type Closure = impl FnOnce();
8+
9+
fn closure() -> Closure {
10+
|| {}
11+
}
12+
13+
struct Wrap<T> { f: T }
14+
15+
impl Wrap<Closure> {}
16+
17+
impl<T> Wrap<T> {}
18+
19+
fn main() {}

0 commit comments

Comments
 (0)