Skip to content

Commit b105e2a

Browse files
committed
Actually prevent cycle errors
1 parent 6e354fb commit b105e2a

19 files changed

+73
-138
lines changed

compiler/rustc_hir_analysis/src/collect/type_of.rs

+7
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use rustc_hir::def_id::{DefId, LocalDefId};
44
use rustc_hir::intravisit;
55
use rustc_hir::intravisit::Visitor;
66
use rustc_hir::{HirId, Node};
7+
use rustc_infer::infer::opaque_types::may_define_opaque_type;
78
use rustc_middle::hir::nested_filter;
89
use rustc_middle::ty::print::with_forced_trimmed_paths;
910
use rustc_middle::ty::subst::InternalSubsts;
@@ -589,6 +590,12 @@ fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> T
589590
debug!("no constraint: no typeck results");
590591
return;
591592
}
593+
594+
if !may_define_opaque_type(self.tcx, item_def_id, self.def_id) {
595+
debug!("no constraint: does not have TAIT in signature");
596+
return;
597+
}
598+
592599
// Calling `mir_borrowck` can lead to cycle errors through
593600
// const-checking, avoid calling it if we don't have to.
594601
// ```rust

compiler/rustc_infer/src/infer/opaque_types.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -638,11 +638,19 @@ impl<'tcx> InferCtxt<'tcx> {
638638
/// and `opaque_hir_id` is the `HirId` of the definition of the opaque type `Baz`.
639639
/// For the above example, this function returns `true` for `f1` and `false` for `f2`.
640640
#[instrument(skip(tcx), level = "trace", ret)]
641-
fn may_define_opaque_type<'tcx>(
641+
pub fn may_define_opaque_type<'tcx>(
642642
tcx: TyCtxt<'tcx>,
643643
def_id: LocalDefId,
644644
opaque_def_id: LocalDefId,
645645
) -> bool {
646+
if tcx.is_closure(def_id.to_def_id()) {
647+
return may_define_opaque_type(
648+
tcx,
649+
tcx.parent(def_id.to_def_id()).expect_local(),
650+
opaque_def_id,
651+
);
652+
}
653+
646654
let param_env = tcx.param_env(def_id);
647655
let opaque_hir_id = tcx.hir().local_def_id_to_hir_id(opaque_def_id);
648656
let mut hir_id = tcx.hir().local_def_id_to_hir_id(def_id);

tests/ui/type-alias-impl-trait/auto-trait-leakage3.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
#![feature(type_alias_impl_trait)]
22
#![allow(dead_code)]
33

4-
// FIXME This should compile, but it currently doesn't
4+
// check-pass
55

66
mod m {
77
type Foo = impl std::fmt::Debug;
8-
//~^ ERROR: cycle detected when computing type of `m::Foo::{opaque#0}` [E0391]
98

109
pub fn foo() -> Foo {
1110
22_u32

tests/ui/type-alias-impl-trait/auto-trait-leakage3.stderr

-22
This file was deleted.

tests/ui/type-alias-impl-trait/defining-scopes-cycle-prevention.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
#![feature(type_alias_impl_trait)]
22

3+
// check-pass
4+
35
// Check that, even within the defining scope, we can get the
46
// `Send` or `Sync` bound of a TAIT, as long as the current function
57
// doesn't mention those TAITs in the signature
68
type Foo = impl std::fmt::Debug;
7-
//~^ ERROR cycle detected
89

910
fn is_send<T: Send>() {}
1011

tests/ui/type-alias-impl-trait/defining-scopes-cycle-prevention.stderr

-28
This file was deleted.

tests/ui/type-alias-impl-trait/defining-scopes-syntactic.rs

+2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ type DropType<T> = ();
77
//~^ ERROR type parameter `T` is unused
88

99
type Foo = impl std::fmt::Debug;
10+
//~^ ERROR unconstrained opaque type
11+
1012
// Check that, even though `Foo` is not part
1113
// of the actual type, we do allow this to be a defining scope
1214
fn g() -> DropType<Foo> {

tests/ui/type-alias-impl-trait/defining-scopes-syntactic.stderr

+10-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,16 @@ error[E0091]: type parameter `T` is unused
44
LL | type DropType<T> = ();
55
| ^ unused type parameter
66

7+
error: unconstrained opaque type
8+
--> $DIR/defining-scopes-syntactic.rs:9:12
9+
|
10+
LL | type Foo = impl std::fmt::Debug;
11+
| ^^^^^^^^^^^^^^^^^^^^
12+
|
13+
= note: `Foo` must be used in combination with a concrete type within the same module
14+
715
error[E0308]: mismatched types
8-
--> $DIR/defining-scopes-syntactic.rs:13:18
16+
--> $DIR/defining-scopes-syntactic.rs:15:18
917
|
1018
LL | type Foo = impl std::fmt::Debug;
1119
| -------------------- the expected opaque type
@@ -18,7 +26,7 @@ LL | let _: Foo = 42;
1826
= note: expected opaque type `Foo`
1927
found type `{integer}`
2028

21-
error: aborting due to 2 previous errors
29+
error: aborting due to 3 previous errors
2230

2331
Some errors have detailed explanations: E0091, E0308.
2432
For more information about an error, try `rustc --explain E0091`.

tests/ui/type-alias-impl-trait/defining-scopes.stderr

-17
This file was deleted.

tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound.rs

+10-7
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,20 @@
33
use std::fmt::Debug;
44

55
type Foo = impl Debug;
6-
pub trait Yay { }
7-
impl Yay for Foo { }
6+
pub trait Yay {}
7+
impl Yay for Foo {}
88

9-
fn foo() {
10-
is_yay::<u32>(); //~ ERROR: the trait bound `u32: Yay` is not satisfied
9+
fn foo()
10+
where
11+
Foo: Debug,
12+
{
13+
is_yay::<u32>(); //~ ERROR: the trait bound `u32: Yay` is not satisfied
1114
is_debug::<u32>(); // OK
12-
is_yay::<Foo>(); // OK
15+
is_yay::<Foo>(); // OK
1316
is_debug::<Foo>(); // OK
1417
}
1518

16-
fn is_yay<T: Yay>() { }
17-
fn is_debug<T: Debug>() { }
19+
fn is_yay<T: Yay>() {}
20+
fn is_debug<T: Debug>() {}
1821

1922
fn main() {}

tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
error[E0277]: the trait bound `u32: Yay` is not satisfied
2-
--> $DIR/impl_trait_for_tait_bound.rs:10:14
2+
--> $DIR/impl_trait_for_tait_bound.rs:13:14
33
|
44
LL | is_yay::<u32>();
55
| ^^^ the trait `Yay` is not implemented for `u32`
66
|
77
= help: the trait `Yay` is implemented for `Foo`
88
note: required by a bound in `is_yay`
9-
--> $DIR/impl_trait_for_tait_bound.rs:16:14
9+
--> $DIR/impl_trait_for_tait_bound.rs:19:14
1010
|
11-
LL | fn is_yay<T: Yay>() { }
11+
LL | fn is_yay<T: Yay>() {}
1212
| ^^^ required by this bound in `is_yay`
1313

1414
error: aborting due to previous error

tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound2.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,14 @@
22

33
use std::fmt::Debug;
44

5-
type Foo = impl Debug;
6-
7-
pub trait Yay { }
8-
impl Yay for u32 { }
5+
pub trait Yay {}
6+
impl Yay for u32 {}
97

108
fn foo() {
9+
type Foo = impl Debug;
1110
is_yay::<Foo>(); //~ ERROR: the trait bound `Foo: Yay` is not satisfied
1211
}
1312

14-
fn is_yay<T: Yay>() { }
13+
fn is_yay<T: Yay>() {}
1514

1615
fn main() {}

tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound2.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
error[E0277]: the trait bound `Foo: Yay` is not satisfied
2-
--> $DIR/impl_trait_for_tait_bound2.rs:11:14
2+
--> $DIR/impl_trait_for_tait_bound2.rs:10:14
33
|
44
LL | is_yay::<Foo>();
55
| ^^^ the trait `Yay` is not implemented for `Foo`
66
|
77
= help: the trait `Yay` is implemented for `u32`
88
note: required by a bound in `is_yay`
9-
--> $DIR/impl_trait_for_tait_bound2.rs:14:14
9+
--> $DIR/impl_trait_for_tait_bound2.rs:13:14
1010
|
11-
LL | fn is_yay<T: Yay>() { }
11+
LL | fn is_yay<T: Yay>() {}
1212
| ^^^ required by this bound in `is_yay`
1313

1414
error: aborting due to previous error

tests/ui/type-alias-impl-trait/inference-cycle.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33

44
mod m {
55
type Foo = impl std::fmt::Debug;
6-
//~^ ERROR cycle detected
76

87
// Cycle: error today, but it'd be nice if it eventually worked
98

@@ -17,6 +16,7 @@ mod m {
1716

1817
fn baz() -> Foo {
1918
let f: Foo = 22_u32;
19+
//~^ ERROR concrete type differs
2020
f
2121
}
2222

Original file line numberDiff line numberDiff line change
@@ -1,22 +1,14 @@
1-
error[E0391]: cycle detected when computing type of `m::Foo::{opaque#0}`
2-
--> $DIR/inference-cycle.rs:5:16
1+
error: concrete type differs from previous defining opaque type use
2+
--> $DIR/inference-cycle.rs:18:22
33
|
4-
LL | type Foo = impl std::fmt::Debug;
5-
| ^^^^^^^^^^^^^^^^^^^^
4+
LL | let f: Foo = 22_u32;
5+
| ^^^^^^ expected `()`, got `u32`
66
|
7-
note: ...which requires type-checking `m::bar`...
8-
--> $DIR/inference-cycle.rs:15:9
7+
note: previous use here
8+
--> $DIR/inference-cycle.rs:10:9
99
|
10-
LL | is_send(foo()); // Today: error
11-
| ^^^^^^^
12-
= note: ...which requires evaluating trait selection obligation `m::Foo: core::marker::Send`...
13-
= note: ...which again requires computing type of `m::Foo::{opaque#0}`, completing the cycle
14-
note: cycle used when checking item types in module `m`
15-
--> $DIR/inference-cycle.rs:4:1
16-
|
17-
LL | mod m {
18-
| ^^^^^
10+
LL | is_send(bar())
11+
| ^^^^^^^^^^^^^^
1912

2013
error: aborting due to previous error
2114

22-
For more information about this error, try `rustc --explain E0391`.

tests/ui/type-alias-impl-trait/nested.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#![feature(type_alias_impl_trait)]
22

33
type Foo = impl std::fmt::Debug;
4+
//~^ ERROR: unconstrained opaque type
45
type Bar = impl Trait<Foo>;
56

67
trait Trait<T> {}
+10-2
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,20 @@
1+
error: unconstrained opaque type
2+
--> $DIR/nested.rs:3:12
3+
|
4+
LL | type Foo = impl std::fmt::Debug;
5+
| ^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: `Foo` must be used in combination with a concrete type within the same module
8+
19
error[E0277]: `Bar` doesn't implement `Debug`
2-
--> $DIR/nested.rs:15:22
10+
--> $DIR/nested.rs:16:22
311
|
412
LL | println!("{:?}", bar());
513
| ^^^^^ `Bar` cannot be formatted using `{:?}` because it doesn't implement `Debug`
614
|
715
= help: the trait `Debug` is not implemented for `Bar`
816
= note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
917

10-
error: aborting due to previous error
18+
error: aborting due to 2 previous errors
1119

1220
For more information about this error, try `rustc --explain E0277`.

tests/ui/type-alias-impl-trait/reveal_local.rs

-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ use std::fmt::Debug;
44

55
type Foo = impl Debug;
66
//~^ ERROR cycle detected
7-
//~| ERROR cycle detected
87

98
fn is_send<T: Send>() {}
109

Original file line numberDiff line numberDiff line change
@@ -1,36 +1,11 @@
1-
error[E0391]: cycle detected when computing type of `Foo::{opaque#0}`
2-
--> $DIR/reveal_local.rs:5:12
3-
|
4-
LL | type Foo = impl Debug;
5-
| ^^^^^^^^^^
6-
|
7-
note: ...which requires type-checking `not_good`...
8-
--> $DIR/reveal_local.rs:14:5
9-
|
10-
LL | is_send::<Foo>();
11-
| ^^^^^^^^^^^^^^
12-
= note: ...which requires evaluating trait selection obligation `Foo: core::marker::Send`...
13-
= note: ...which again requires computing type of `Foo::{opaque#0}`, completing the cycle
14-
note: cycle used when checking item types in top-level module
15-
--> $DIR/reveal_local.rs:1:1
16-
|
17-
LL | / #![feature(type_alias_impl_trait)]
18-
LL | |
19-
LL | | use std::fmt::Debug;
20-
LL | |
21-
... |
22-
LL | |
23-
LL | | fn main() {}
24-
| |____________^
25-
261
error[E0391]: cycle detected when computing type of `Foo::{opaque#0}`
272
--> $DIR/reveal_local.rs:5:12
283
|
294
LL | type Foo = impl Debug;
305
| ^^^^^^^^^^
316
|
327
note: ...which requires type-checking `not_gooder`...
33-
--> $DIR/reveal_local.rs:26:5
8+
--> $DIR/reveal_local.rs:25:5
349
|
3510
LL | is_send::<Foo>();
3611
| ^^^^^^^^^^^^^^
@@ -48,6 +23,6 @@ LL | |
4823
LL | | fn main() {}
4924
| |____________^
5025

51-
error: aborting due to 2 previous errors
26+
error: aborting due to previous error
5227

5328
For more information about this error, try `rustc --explain E0391`.

0 commit comments

Comments
 (0)