diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index b573c4b43906c..b8437756c6970 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -332,11 +332,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self.assemble_candidates_from_projected_tys(obligation, &mut candidates); self.assemble_candidates_from_caller_bounds(stack, &mut candidates)?; - // Auto implementations have lower priority, so we only - // consider triggering a default if there is no other impl that can apply. - if candidates.vec.is_empty() { - self.assemble_candidates_from_auto_impls(obligation, &mut candidates); - } + self.assemble_candidates_from_auto_impls(obligation, &mut candidates); } debug!("candidate list size: {}", candidates.vec.len()); Ok(candidates) @@ -600,7 +596,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // for an example of a test case that exercises // this path. } - ty::Infer(ty::TyVar(_)) => { + ty::Infer(ty::TyVar(_) | ty::IntVar(_) | ty::FloatVar(_)) => { // The auto impl might apply; we don't know. candidates.ambiguous = true; } @@ -620,7 +616,62 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } - _ => candidates.vec.push(AutoImplCandidate(def_id)), + ty::Placeholder(..) + | ty::Bound(..) + | ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => { + bug!( + "asked to assemble auto trait candidates of unexpected type: {:?}", + self_ty + ); + } + + ty::Opaque(_, _) + if candidates.vec.iter().any(|c| matches!(c, ProjectionCandidate(_))) => + { + // We do not generate an auto impl candidate for `impl Trait`s which already + // reference our auto trait. + // + // For example during candidate assembly for `impl Send: Send`, we don't have + // to look at the constituent types for this opaque types to figure out that this + // trivially holds. + // + // Note that this is only sound as projection candidates of opaque types + // are always applicable for auto traits. + } + + ty::Bool + | ty::Char + | ty::Int(_) + | ty::Uint(_) + | ty::Float(_) + | ty::Str + | ty::Array(_, _) + | ty::Slice(_) + | ty::Adt(..) + | ty::RawPtr(_) + | ty::Ref(..) + | ty::FnDef(..) + | ty::FnPtr(_) + | ty::Closure(_, _) + | ty::Generator(..) + | ty::Never + | ty::Tuple(_) + | ty::Opaque(_, _) + | ty::GeneratorWitness(_) => { + // Only consider auto impls if there are no manual impls for the root of `self_ty`. + // + // For example, we only consider auto candidates for `&i32: Auto` if no explicit impl + // for `&SomeType: Auto` exists. Due to E0321 the only crate where impls + // for `&SomeType: Auto` can be defined is the crate where `Auto` has been defined. + // + // Generally, we have to guarantee that for all `SimplifiedType`s the only crate + // which may define impls for that type is either the crate defining the type + // or the trait. This should be guaranteed by the orphan check. + if self.tcx().find_map_relevant_impl(def_id, self_ty, |_| Some(())).is_none() { + candidates.vec.push(AutoImplCandidate(def_id)) + } + } + ty::Error(_) => {} // do not add an auto trait impl for `ty::Error` for now. } } } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 1414c742635c4..2c1a32abf25ad 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1518,6 +1518,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /// candidates and prefer where-clause candidates. /// /// See the comment for "SelectionCandidate" for more details. + #[instrument(level = "debug", skip(self, needs_infer))] fn candidate_should_be_dropped_in_favor_of( &mut self, sized_predicate: bool, @@ -1542,13 +1543,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // This is a fix for #53123 and prevents winnowing from accidentally extending the // lifetime of a variable. match (&other.candidate, &victim.candidate) { - (_, AutoImplCandidate(..)) | (AutoImplCandidate(..), _) => { - bug!( - "default implementations shouldn't be recorded \ - when there are other valid candidates" - ); - } - // (*) ( BuiltinCandidate { has_nested: false } @@ -1610,6 +1604,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ( ParamCandidate(ref cand), ImplCandidate(..) + | AutoImplCandidate(_) | ClosureCandidate | GeneratorCandidate | FnPointerCandidate { .. } @@ -1621,6 +1616,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) => !is_global(cand), ( ImplCandidate(_) + | AutoImplCandidate(_) | ClosureCandidate | GeneratorCandidate | FnPointerCandidate { .. } @@ -1651,6 +1647,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ( ObjectCandidate(_) | ProjectionCandidate(_), ImplCandidate(..) + | AutoImplCandidate(_) | ClosureCandidate | GeneratorCandidate | FnPointerCandidate { .. } @@ -1663,6 +1660,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ( ImplCandidate(..) + | AutoImplCandidate(_) | ClosureCandidate | GeneratorCandidate | FnPointerCandidate { .. } @@ -1741,6 +1739,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } + (AutoImplCandidate(_), ImplCandidate(_)) | (ImplCandidate(_), AutoImplCandidate(_)) => { + false + } + + (AutoImplCandidate(_), _) | (_, AutoImplCandidate(_)) => { + bug!( + "default implementations shouldn't be recorded \ + when there are other global candidates: {:?} {:?}", + other, + victim + ); + } + // Everything else is ambiguous ( ImplCandidate(_) diff --git a/src/test/ui/auto-traits/issue-83857-ub.rs b/src/test/ui/auto-traits/issue-83857-ub.rs new file mode 100644 index 0000000000000..4a38a6fff8d5b --- /dev/null +++ b/src/test/ui/auto-traits/issue-83857-ub.rs @@ -0,0 +1,29 @@ +struct Always(T, U); +unsafe impl Send for Always {} +struct Foo(Always); + +trait False {} +unsafe impl Send for Foo {} + +trait WithAssoc { + type Output; +} +impl WithAssoc for T { + type Output = Self; +} +impl WithAssoc for Foo { + type Output = Box; +} + +fn generic(v: Foo, f: fn( as WithAssoc>::Output) -> i32) { + //~^ ERROR `Foo` cannot be sent between threads safely + f(foo(v)); +} + +fn foo(x: T) -> ::Output { + x +} + +fn main() { + generic(Foo(Always(0, ())), |b| *b); +} diff --git a/src/test/ui/auto-traits/issue-83857-ub.stderr b/src/test/ui/auto-traits/issue-83857-ub.stderr new file mode 100644 index 0000000000000..3c2a521c61033 --- /dev/null +++ b/src/test/ui/auto-traits/issue-83857-ub.stderr @@ -0,0 +1,16 @@ +error[E0277]: `Foo` cannot be sent between threads safely + --> $DIR/issue-83857-ub.rs:18:38 + | +LL | fn generic(v: Foo, f: fn( as WithAssoc>::Output) -> i32) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Foo` cannot be sent between threads safely + | + = help: the trait `Send` is not implemented for `Foo` + = note: required because of the requirements on the impl of `WithAssoc` for `Foo` +help: consider introducing a `where` bound, but there might be an alternative better way to express this requirement + | +LL | fn generic(v: Foo, f: fn( as WithAssoc>::Output) -> i32) where Foo: Send { + | +++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/generator/auto-trait-regions.rs b/src/test/ui/generator/auto-trait-regions.rs index 8f1e4f1b66f48..59e4118ca0f91 100644 --- a/src/test/ui/generator/auto-trait-regions.rs +++ b/src/test/ui/generator/auto-trait-regions.rs @@ -23,7 +23,7 @@ fn assert_foo(f: T) {} fn main() { // Make sure 'static is erased for generator interiors so we can't match it in trait selection let x: &'static _ = &OnlyFooIfStaticRef(No); - let gen = || { + let gen = move || { let x = x; yield; assert_foo(x); @@ -34,7 +34,7 @@ fn main() { // Allow impls which matches any lifetime let x = &OnlyFooIfRef(No); - let gen = || { + let gen = move || { let x = x; yield; assert_foo(x); @@ -42,7 +42,7 @@ fn main() { assert_foo(gen); // ok // Disallow impls which relates lifetimes in the generator interior - let gen = || { + let gen = move || { let a = A(&mut true, &mut true, No); yield; assert_foo(a); diff --git a/src/test/ui/impl-trait/auto-trait-leak.rs b/src/test/ui/impl-trait/auto-trait-leak.rs index c2fbbf94fd666..e8541c565aee6 100644 --- a/src/test/ui/impl-trait/auto-trait-leak.rs +++ b/src/test/ui/impl-trait/auto-trait-leak.rs @@ -11,6 +11,8 @@ fn main() { // return type, which can't depend on the obligation. fn cycle1() -> impl Clone { //~^ ERROR cycle detected + //~| ERROR cycle detected + //~| ERROR cycle detected send(cycle2().clone()); Rc::new(Cell::new(5)) diff --git a/src/test/ui/impl-trait/auto-trait-leak.stderr b/src/test/ui/impl-trait/auto-trait-leak.stderr index 634ff14869eb4..69988eb997c0f 100644 --- a/src/test/ui/impl-trait/auto-trait-leak.stderr +++ b/src/test/ui/impl-trait/auto-trait-leak.stderr @@ -30,43 +30,43 @@ note: ...which requires building MIR for `cycle1`... LL | fn cycle1() -> impl Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires type-checking `cycle1`... - --> $DIR/auto-trait-leak.rs:14:5 + --> $DIR/auto-trait-leak.rs:16:5 | LL | send(cycle2().clone()); | ^^^^ = note: ...which requires evaluating trait selection obligation `impl core::clone::Clone: core::marker::Send`... note: ...which requires computing type of `cycle2::{opaque#0}`... - --> $DIR/auto-trait-leak.rs:19:16 + --> $DIR/auto-trait-leak.rs:21:16 | LL | fn cycle2() -> impl Clone { | ^^^^^^^^^^ note: ...which requires borrow-checking `cycle2`... - --> $DIR/auto-trait-leak.rs:19:1 + --> $DIR/auto-trait-leak.rs:21:1 | LL | fn cycle2() -> impl Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires processing `cycle2`... - --> $DIR/auto-trait-leak.rs:19:1 + --> $DIR/auto-trait-leak.rs:21:1 | LL | fn cycle2() -> impl Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires processing MIR for `cycle2`... - --> $DIR/auto-trait-leak.rs:19:1 + --> $DIR/auto-trait-leak.rs:21:1 | LL | fn cycle2() -> impl Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires unsafety-checking `cycle2`... - --> $DIR/auto-trait-leak.rs:19:1 + --> $DIR/auto-trait-leak.rs:21:1 | LL | fn cycle2() -> impl Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires building MIR for `cycle2`... - --> $DIR/auto-trait-leak.rs:19:1 + --> $DIR/auto-trait-leak.rs:21:1 | LL | fn cycle2() -> impl Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires type-checking `cycle2`... - --> $DIR/auto-trait-leak.rs:20:5 + --> $DIR/auto-trait-leak.rs:22:5 | LL | send(cycle1().clone()); | ^^^^ @@ -84,6 +84,176 @@ LL | | Rc::new(String::from("foo")) LL | | } | |_^ -error: aborting due to previous error +error[E0391]: cycle detected when computing type of `cycle1::{opaque#0}` + --> $DIR/auto-trait-leak.rs:12:16 + | +LL | fn cycle1() -> impl Clone { + | ^^^^^^^^^^ + | +note: ...which requires borrow-checking `cycle1`... + --> $DIR/auto-trait-leak.rs:12:1 + | +LL | fn cycle1() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires processing `cycle1`... + --> $DIR/auto-trait-leak.rs:12:1 + | +LL | fn cycle1() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires processing MIR for `cycle1`... + --> $DIR/auto-trait-leak.rs:12:1 + | +LL | fn cycle1() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires unsafety-checking `cycle1`... + --> $DIR/auto-trait-leak.rs:12:1 + | +LL | fn cycle1() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires building MIR for `cycle1`... + --> $DIR/auto-trait-leak.rs:12:1 + | +LL | fn cycle1() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires type-checking `cycle1`... + --> $DIR/auto-trait-leak.rs:16:5 + | +LL | send(cycle2().clone()); + | ^^^^ + = note: ...which requires evaluating trait selection obligation `impl core::clone::Clone: core::marker::Send`... +note: ...which requires computing type of `cycle2::{opaque#0}`... + --> $DIR/auto-trait-leak.rs:21:16 + | +LL | fn cycle2() -> impl Clone { + | ^^^^^^^^^^ +note: ...which requires borrow-checking `cycle2`... + --> $DIR/auto-trait-leak.rs:21:1 + | +LL | fn cycle2() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires processing `cycle2`... + --> $DIR/auto-trait-leak.rs:21:1 + | +LL | fn cycle2() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires processing MIR for `cycle2`... + --> $DIR/auto-trait-leak.rs:21:1 + | +LL | fn cycle2() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires unsafety-checking `cycle2`... + --> $DIR/auto-trait-leak.rs:21:1 + | +LL | fn cycle2() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires building MIR for `cycle2`... + --> $DIR/auto-trait-leak.rs:21:1 + | +LL | fn cycle2() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires type-checking `cycle2`... + --> $DIR/auto-trait-leak.rs:21:1 + | +LL | fn cycle2() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: ...which again requires computing type of `cycle1::{opaque#0}`, completing the cycle +note: cycle used when checking item types in top-level module + --> $DIR/auto-trait-leak.rs:1:1 + | +LL | / use std::cell::Cell; +LL | | use std::rc::Rc; +LL | | +LL | | fn send(_: T) {} +... | +LL | | Rc::new(String::from("foo")) +LL | | } + | |_^ + +error[E0391]: cycle detected when computing type of `cycle1::{opaque#0}` + --> $DIR/auto-trait-leak.rs:12:16 + | +LL | fn cycle1() -> impl Clone { + | ^^^^^^^^^^ + | +note: ...which requires borrow-checking `cycle1`... + --> $DIR/auto-trait-leak.rs:12:1 + | +LL | fn cycle1() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires processing `cycle1`... + --> $DIR/auto-trait-leak.rs:12:1 + | +LL | fn cycle1() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires processing MIR for `cycle1`... + --> $DIR/auto-trait-leak.rs:12:1 + | +LL | fn cycle1() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires unsafety-checking `cycle1`... + --> $DIR/auto-trait-leak.rs:12:1 + | +LL | fn cycle1() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires building MIR for `cycle1`... + --> $DIR/auto-trait-leak.rs:12:1 + | +LL | fn cycle1() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires type-checking `cycle1`... + --> $DIR/auto-trait-leak.rs:16:5 + | +LL | send(cycle2().clone()); + | ^^^^ + = note: ...which requires evaluating trait selection obligation `impl core::clone::Clone: core::marker::Send`... +note: ...which requires computing type of `cycle2::{opaque#0}`... + --> $DIR/auto-trait-leak.rs:21:16 + | +LL | fn cycle2() -> impl Clone { + | ^^^^^^^^^^ +note: ...which requires borrow-checking `cycle2`... + --> $DIR/auto-trait-leak.rs:21:1 + | +LL | fn cycle2() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires processing `cycle2`... + --> $DIR/auto-trait-leak.rs:21:1 + | +LL | fn cycle2() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires processing MIR for `cycle2`... + --> $DIR/auto-trait-leak.rs:21:1 + | +LL | fn cycle2() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires unsafety-checking `cycle2`... + --> $DIR/auto-trait-leak.rs:21:1 + | +LL | fn cycle2() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires building MIR for `cycle2`... + --> $DIR/auto-trait-leak.rs:21:1 + | +LL | fn cycle2() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires type-checking `cycle2`... + --> $DIR/auto-trait-leak.rs:21:1 + | +LL | fn cycle2() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: ...which again requires computing type of `cycle1::{opaque#0}`, completing the cycle +note: cycle used when checking item types in top-level module + --> $DIR/auto-trait-leak.rs:1:1 + | +LL | / use std::cell::Cell; +LL | | use std::rc::Rc; +LL | | +LL | | fn send(_: T) {} +... | +LL | | Rc::new(String::from("foo")) +LL | | } + | |_^ + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0391`. diff --git a/src/test/ui/impl-trait/recursive-auto-trait.rs b/src/test/ui/impl-trait/recursive-auto-trait.rs new file mode 100644 index 0000000000000..d7b68144ff6ba --- /dev/null +++ b/src/test/ui/impl-trait/recursive-auto-trait.rs @@ -0,0 +1,10 @@ +// check-pass +fn is_send(_: T) {} +fn foo() -> impl Send { + if false { + is_send(foo()); + } + () +} + +fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.rs b/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.rs index 5fb7a9473d3df..b699d060006b5 100644 --- a/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.rs +++ b/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.rs @@ -6,6 +6,8 @@ mod m { type Foo = impl std::fmt::Debug; //~^ ERROR: cycle detected when computing type of `m::Foo::{opaque#0}` [E0391] + //~| ERROR: cycle detected when computing type of `m::Foo::{opaque#0}` [E0391] + //~| ERROR: cycle detected when computing type of `m::Foo::{opaque#0}` [E0391] pub fn foo() -> Foo { 22_u32 diff --git a/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.stderr b/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.stderr index c0147e56c9364..d9d29c16a8042 100644 --- a/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.stderr +++ b/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.stderr @@ -5,7 +5,7 @@ LL | type Foo = impl std::fmt::Debug; | ^^^^^^^^^^^^^^^^^^^^ | note: ...which requires type-checking `m::bar`... - --> $DIR/auto-trait-leakage3.rs:15:9 + --> $DIR/auto-trait-leakage3.rs:17:9 | LL | is_send(foo()); | ^^^^^^^ @@ -17,6 +17,42 @@ note: cycle used when checking item types in module `m` LL | mod m { | ^^^^^ -error: aborting due to previous error +error[E0391]: cycle detected when computing type of `m::Foo::{opaque#0}` + --> $DIR/auto-trait-leakage3.rs:7:16 + | +LL | type Foo = impl std::fmt::Debug; + | ^^^^^^^^^^^^^^^^^^^^ + | +note: ...which requires type-checking `m::bar`... + --> $DIR/auto-trait-leakage3.rs:16:5 + | +LL | pub fn bar() { + | ^^^^^^^^^^^^ + = note: ...which again requires computing type of `m::Foo::{opaque#0}`, completing the cycle +note: cycle used when checking item types in module `m` + --> $DIR/auto-trait-leakage3.rs:6:1 + | +LL | mod m { + | ^^^^^ + +error[E0391]: cycle detected when computing type of `m::Foo::{opaque#0}` + --> $DIR/auto-trait-leakage3.rs:7:16 + | +LL | type Foo = impl std::fmt::Debug; + | ^^^^^^^^^^^^^^^^^^^^ + | +note: ...which requires type-checking `m::bar`... + --> $DIR/auto-trait-leakage3.rs:16:5 + | +LL | pub fn bar() { + | ^^^^^^^^^^^^ + = note: ...which again requires computing type of `m::Foo::{opaque#0}`, completing the cycle +note: cycle used when checking item types in module `m` + --> $DIR/auto-trait-leakage3.rs:6:1 + | +LL | mod m { + | ^^^^^ + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0391`. diff --git a/src/test/ui/type-alias-impl-trait/inference-cycle.rs b/src/test/ui/type-alias-impl-trait/inference-cycle.rs index c781e200bf8ee..ea4657e6e68f0 100644 --- a/src/test/ui/type-alias-impl-trait/inference-cycle.rs +++ b/src/test/ui/type-alias-impl-trait/inference-cycle.rs @@ -4,6 +4,8 @@ mod m { type Foo = impl std::fmt::Debug; //~^ ERROR: cycle detected when computing type of `m::Foo::{opaque#0}` [E0391] + //~| ERROR: cycle detected when computing type of `m::Foo::{opaque#0}` [E0391] + //~| ERROR: cycle detected when computing type of `m::Foo::{opaque#0}` [E0391] // Cycle: error today, but it'd be nice if it eventually worked diff --git a/src/test/ui/type-alias-impl-trait/inference-cycle.stderr b/src/test/ui/type-alias-impl-trait/inference-cycle.stderr index e12124664778e..d7f6647622932 100644 --- a/src/test/ui/type-alias-impl-trait/inference-cycle.stderr +++ b/src/test/ui/type-alias-impl-trait/inference-cycle.stderr @@ -5,7 +5,7 @@ LL | type Foo = impl std::fmt::Debug; | ^^^^^^^^^^^^^^^^^^^^ | note: ...which requires type-checking `m::bar`... - --> $DIR/inference-cycle.rs:15:9 + --> $DIR/inference-cycle.rs:17:9 | LL | is_send(foo()); // Today: error | ^^^^^^^ @@ -17,8 +17,44 @@ note: cycle used when checking item types in module `m` LL | mod m { | ^^^^^ +error[E0391]: cycle detected when computing type of `m::Foo::{opaque#0}` + --> $DIR/inference-cycle.rs:5:16 + | +LL | type Foo = impl std::fmt::Debug; + | ^^^^^^^^^^^^^^^^^^^^ + | +note: ...which requires type-checking `m::bar`... + --> $DIR/inference-cycle.rs:16:5 + | +LL | pub fn bar() { + | ^^^^^^^^^^^^ + = note: ...which again requires computing type of `m::Foo::{opaque#0}`, completing the cycle +note: cycle used when checking item types in module `m` + --> $DIR/inference-cycle.rs:4:1 + | +LL | mod m { + | ^^^^^ + +error[E0391]: cycle detected when computing type of `m::Foo::{opaque#0}` + --> $DIR/inference-cycle.rs:5:16 + | +LL | type Foo = impl std::fmt::Debug; + | ^^^^^^^^^^^^^^^^^^^^ + | +note: ...which requires type-checking `m::bar`... + --> $DIR/inference-cycle.rs:16:5 + | +LL | pub fn bar() { + | ^^^^^^^^^^^^ + = note: ...which again requires computing type of `m::Foo::{opaque#0}`, completing the cycle +note: cycle used when checking item types in module `m` + --> $DIR/inference-cycle.rs:4:1 + | +LL | mod m { + | ^^^^^ + error[E0308]: mismatched types - --> $DIR/inference-cycle.rs:19:22 + --> $DIR/inference-cycle.rs:21:22 | LL | type Foo = impl std::fmt::Debug; | -------------------- the expected opaque type @@ -31,7 +67,7 @@ LL | let f: Foo = 22_u32; = note: expected opaque type `impl Debug` found type `u32` -error: aborting due to 2 previous errors +error: aborting due to 4 previous errors Some errors have detailed explanations: E0308, E0391. For more information about an error, try `rustc --explain E0308`.