diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index b11a54d5dcb11..742005e245f9d 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -744,6 +744,7 @@ pub trait PrettyPrinter<'tcx>: p!(print_def_path(did, substs)); if !substs.as_closure().is_valid() { p!(" closure_substs=(unavailable)"); + p!(write(" substs={:?}", substs)); } else { p!(" closure_kind_ty=", print(substs.as_closure().kind_ty())); p!( diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index db8a6d9620495..b8c66931cbe52 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1734,7 +1734,7 @@ fn confirm_callable_candidate<'cx, 'tcx>( ty: ret_type, }); - confirm_param_env_candidate(selcx, obligation, predicate, false) + confirm_param_env_candidate(selcx, obligation, predicate, true) } fn confirm_param_env_candidate<'cx, 'tcx>( @@ -1754,8 +1754,18 @@ fn confirm_param_env_candidate<'cx, 'tcx>( ); let cache_projection = cache_entry.projection_ty; - let obligation_projection = obligation.predicate; let mut nested_obligations = Vec::new(); + let obligation_projection = obligation.predicate; + let obligation_projection = ensure_sufficient_stack(|| { + normalize_with_depth_to( + selcx, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth + 1, + obligation_projection, + &mut nested_obligations, + ) + }); let cache_projection = if potentially_unnormalized_candidate { ensure_sufficient_stack(|| { normalize_with_depth_to( @@ -1771,6 +1781,8 @@ fn confirm_param_env_candidate<'cx, 'tcx>( cache_projection }; + debug!(?cache_projection, ?obligation_projection); + match infcx.at(cause, param_env).eq(cache_projection, obligation_projection) { Ok(InferOk { value: _, obligations }) => { nested_obligations.extend(obligations); diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index a36cb1358b64c..a4e2e5028333b 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -620,23 +620,37 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { _ => bug!("closure candidate for non-closure {:?}", obligation), }; + let obligation_predicate = obligation.predicate.to_poly_trait_ref(); + let Normalized { value: obligation_predicate, mut obligations } = + ensure_sufficient_stack(|| { + normalize_with_depth( + self, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth + 1, + obligation_predicate, + ) + }); + let trait_ref = self.closure_trait_ref_unnormalized(obligation, substs); - let Normalized { value: trait_ref, mut obligations } = ensure_sufficient_stack(|| { - normalize_with_depth( - self, - obligation.param_env, - obligation.cause.clone(), - obligation.recursion_depth + 1, - trait_ref, - ) - }); + let Normalized { value: trait_ref, obligations: trait_ref_obligations } = + ensure_sufficient_stack(|| { + normalize_with_depth( + self, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth + 1, + trait_ref, + ) + }); debug!(?closure_def_id, ?trait_ref, ?obligations, "confirm closure candidate obligations"); + obligations.extend(trait_ref_obligations); obligations.extend(self.confirm_poly_trait_refs( obligation.cause.clone(), obligation.param_env, - obligation.predicate.to_poly_trait_ref(), + obligation_predicate, trait_ref, )?); diff --git a/src/test/ui/closures/print/closure-print-generic-trim-off-verbose-2.stderr b/src/test/ui/closures/print/closure-print-generic-trim-off-verbose-2.stderr index d9479002b6cde..36d6450c9a2f0 100644 --- a/src/test/ui/closures/print/closure-print-generic-trim-off-verbose-2.stderr +++ b/src/test/ui/closures/print/closure-print-generic-trim-off-verbose-2.stderr @@ -9,7 +9,7 @@ LL | let c1 : () = c; | expected due to this | = note: expected unit type `()` - found closure `[mod1::f::{closure#0} closure_substs=(unavailable)]` + found closure `[mod1::f::{closure#0} closure_substs=(unavailable) substs=[T, _#25t, extern "rust-call" fn(()), _#26t]]` help: use parentheses to call this closure | LL | let c1 : () = c(); diff --git a/src/test/ui/closures/print/closure-print-generic-verbose-2.stderr b/src/test/ui/closures/print/closure-print-generic-verbose-2.stderr index 880e38df2d70a..91926f233d394 100644 --- a/src/test/ui/closures/print/closure-print-generic-verbose-2.stderr +++ b/src/test/ui/closures/print/closure-print-generic-verbose-2.stderr @@ -9,7 +9,7 @@ LL | let c1 : () = c; | expected due to this | = note: expected unit type `()` - found closure `[f::{closure#0} closure_substs=(unavailable)]` + found closure `[f::{closure#0} closure_substs=(unavailable) substs=[T, _#25t, extern "rust-call" fn(()), _#26t]]` help: use parentheses to call this closure | LL | let c1 : () = c(); diff --git a/src/test/ui/closures/print/closure-print-verbose.stderr b/src/test/ui/closures/print/closure-print-verbose.stderr index d19b07acbf175..083717b333408 100644 --- a/src/test/ui/closures/print/closure-print-verbose.stderr +++ b/src/test/ui/closures/print/closure-print-verbose.stderr @@ -7,7 +7,7 @@ LL | let foo: fn(u8) -> u8 = |v: u8| { a += v; a }; | expected due to this | = note: expected fn pointer `fn(u8) -> u8` - found closure `[main::{closure#0} closure_substs=(unavailable)]` + found closure `[main::{closure#0} closure_substs=(unavailable) substs=[i8, extern "rust-call" fn((u8,)) -> u8, _#6t]]` note: closures can only be coerced to `fn` types if they do not capture any variables --> $DIR/closure-print-verbose.rs:10:39 | diff --git a/src/test/ui/generic-associated-types/issue-88459.rs b/src/test/ui/generic-associated-types/issue-88459.rs new file mode 100644 index 0000000000000..3b26a180152cb --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-88459.rs @@ -0,0 +1,19 @@ +// check-pass + +#![feature(generic_associated_types)] + +trait Trait { + type Assoc<'a>; +} + +fn f(_: T, _: impl Fn(T::Assoc<'_>)) {} + +struct Type; + +impl Trait for Type { + type Assoc<'a> = (); +} + +fn main() { + f(Type, |_|()); +} diff --git a/src/test/ui/issues/issue-44005.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-44005.rs similarity index 95% rename from src/test/ui/issues/issue-44005.rs rename to src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-44005.rs index ab3b92142c8c9..f255eac0c4b2c 100644 --- a/src/test/ui/issues/issue-44005.rs +++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-44005.rs @@ -1,3 +1,5 @@ +// check-pass + pub trait Foo<'a> { type Bar; fn foo(&'a self) -> Self::Bar; @@ -24,7 +26,6 @@ pub fn catalyst(x: &i32) { pub fn broken(x: &i32, f: F) { uncallable(x, |y| f(y)); - //~^ type mismatch } fn main() {} diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-56556.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-56556.rs new file mode 100644 index 0000000000000..768d1c36619da --- /dev/null +++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-56556.rs @@ -0,0 +1,13 @@ +// check-pass + +fn foo(t: T) -> usize +where + for<'a> &'a T: IntoIterator, + for<'a> <&'a T as IntoIterator>::IntoIter: ExactSizeIterator, +{ + t.into_iter().len() +} + +fn main() { + foo::>(vec![]); +} diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.rs index 24ac566f9df0c..7c3c72e04cb78 100644 --- a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.rs +++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.rs @@ -77,7 +77,7 @@ where P: Execute + 'static { } fn main() { - task(annotate( //~ type mismatch + task(annotate( //~^ the size //~^^ the trait bound Annotate::>::new(), diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.stderr b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.stderr index b13226fef6e76..01b14660b6531 100644 --- a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.stderr +++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.stderr @@ -1,29 +1,3 @@ -error[E0631]: type mismatch in closure arguments - --> $DIR/issue-62529-1.rs:80:10 - | -LL | task(annotate( - | _____----_^ - | | | - | | required by a bound introduced by this call -LL | | -LL | | -LL | | Annotate::>::new(), -LL | | |value: &mut usize| { - | | ------------------- found signature of `for<'r> fn(&'r mut usize) -> _` -LL | | *value = 2; -LL | | } -LL | | )); - | |_____^ expected signature of `for<'r> fn( as FamilyLt<'r>>::Out) -> _` - | -note: required by a bound in `annotate` - --> $DIR/issue-62529-1.rs:44:8 - | -LL | fn annotate(_q: Annotate, func: F) -> impl Execute + 'static - | -------- required by a bound in this -LL | where -LL | F: for<'r> FnOnce(<::I as FamilyLt<'r>>::Out) + 'static, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `annotate` - error[E0277]: the size for values of type `impl Execute` cannot be known at compilation time --> $DIR/issue-62529-1.rs:80:10 | @@ -73,7 +47,6 @@ LL | fn task

(processor: P) -> Task LL | where P: Execute + 'static { | ^^^^^^^ required by this bound in `task` -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0277, E0631. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-70120.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-70120.rs index 87d1a250f7ae6..3ced40230f012 100644 --- a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-70120.rs +++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-70120.rs @@ -1,3 +1,5 @@ +// check-pass + pub trait MyTrait<'a> { type Output: 'a; fn gimme_value(&self) -> Self::Output; @@ -23,7 +25,7 @@ where fn main() { let struc = MyStruct; - meow(struc, |foo| { //~ type mismatch + meow(struc, |foo| { println!("{:?}", foo); }) } diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-70120.stderr b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-70120.stderr deleted file mode 100644 index efc956888ee5a..0000000000000 --- a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-70120.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error[E0631]: type mismatch in closure arguments - --> $DIR/issue-70120.rs:26:5 - | -LL | meow(struc, |foo| { - | ^^^^ ----- found signature of `for<'r> fn(&'r usize) -> _` - | | - | expected signature of `for<'any2> fn(>::Output) -> _` - | -note: required by a bound in `meow` - --> $DIR/issue-70120.rs:18:8 - | -LL | fn meow(t: T, f: F) - | ---- required by a bound in this -... -LL | F: for<'any2> Fn(>::Output), - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `meow` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0631`. diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.migrate.stderr b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.migrate.stderr new file mode 100644 index 0000000000000..119cec1fa95bf --- /dev/null +++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.migrate.stderr @@ -0,0 +1,92 @@ +error: implementation of `Parser` is not general enough + --> $DIR/issue-71955.rs:52:5 + | +LL | foo(bar, "string", |s| s.len() == 5); + | ^^^ implementation of `Parser` is not general enough + | + = note: `for<'a> fn(&'a str) -> (&'a str, &'a str) {bar}` must implement `Parser<'0>`, for any lifetime `'0`... + = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1` + +error: implementation of `Parser` is not general enough + --> $DIR/issue-71955.rs:52:5 + | +LL | foo(bar, "string", |s| s.len() == 5); + | ^^^ implementation of `Parser` is not general enough + | + = note: `for<'a> fn(&'a str) -> (&'a str, &'a str) {bar}` must implement `Parser<'0>`, for any lifetime `'0`... + = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1` + +error: implementation of `Parser` is not general enough + --> $DIR/issue-71955.rs:52:5 + | +LL | foo(bar, "string", |s| s.len() == 5); + | ^^^ implementation of `Parser` is not general enough + | + = note: `for<'a> fn(&'a str) -> (&'a str, &'a str) {bar}` must implement `Parser<'0>`, for any lifetime `'0`... + = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1` + +error: implementation of `Parser` is not general enough + --> $DIR/issue-71955.rs:52:5 + | +LL | foo(bar, "string", |s| s.len() == 5); + | ^^^ implementation of `Parser` is not general enough + | + = note: `for<'a> fn(&'a str) -> (&'a str, &'a str) {bar}` must implement `Parser<'0>`, for any lifetime `'0`... + = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1` + +error: implementation of `Parser` is not general enough + --> $DIR/issue-71955.rs:52:5 + | +LL | foo(bar, "string", |s| s.len() == 5); + | ^^^ implementation of `Parser` is not general enough + | + = note: `for<'a> fn(&'a str) -> (&'a str, &'a str) {bar}` must implement `Parser<'0>`, for any lifetime `'0`... + = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1` + +error: implementation of `Parser` is not general enough + --> $DIR/issue-71955.rs:58:5 + | +LL | foo(baz, "string", |s| s.0.len() == 5); + | ^^^ implementation of `Parser` is not general enough + | + = note: `for<'a> fn(&'a str) -> (&'a str, Wrapper<'a>) {baz}` must implement `Parser<'0>`, for any lifetime `'0`... + = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1` + +error: implementation of `Parser` is not general enough + --> $DIR/issue-71955.rs:58:5 + | +LL | foo(baz, "string", |s| s.0.len() == 5); + | ^^^ implementation of `Parser` is not general enough + | + = note: `for<'a> fn(&'a str) -> (&'a str, Wrapper<'a>) {baz}` must implement `Parser<'0>`, for any lifetime `'0`... + = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1` + +error: implementation of `Parser` is not general enough + --> $DIR/issue-71955.rs:58:5 + | +LL | foo(baz, "string", |s| s.0.len() == 5); + | ^^^ implementation of `Parser` is not general enough + | + = note: `for<'a> fn(&'a str) -> (&'a str, Wrapper<'a>) {baz}` must implement `Parser<'0>`, for any lifetime `'0`... + = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1` + +error: implementation of `Parser` is not general enough + --> $DIR/issue-71955.rs:58:5 + | +LL | foo(baz, "string", |s| s.0.len() == 5); + | ^^^ implementation of `Parser` is not general enough + | + = note: `for<'a> fn(&'a str) -> (&'a str, Wrapper<'a>) {baz}` must implement `Parser<'0>`, for any lifetime `'0`... + = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1` + +error: implementation of `Parser` is not general enough + --> $DIR/issue-71955.rs:58:5 + | +LL | foo(baz, "string", |s| s.0.len() == 5); + | ^^^ implementation of `Parser` is not general enough + | + = note: `for<'a> fn(&'a str) -> (&'a str, Wrapper<'a>) {baz}` must implement `Parser<'0>`, for any lifetime `'0`... + = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1` + +error: aborting due to 10 previous errors + diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.nll.stderr b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.nll.stderr new file mode 100644 index 0000000000000..69ab446bc7a34 --- /dev/null +++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.nll.stderr @@ -0,0 +1,8 @@ +error: fatal error triggered by #[rustc_error] + --> $DIR/issue-71955.rs:42:1 + | +LL | fn main() { + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.rs new file mode 100644 index 0000000000000..95e3b3d4e1b88 --- /dev/null +++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.rs @@ -0,0 +1,64 @@ +// ignore-compare-mode-nll +// revisions: migrate nll +// [nll]compile-flags: -Zborrowck=mir +// check-fail + +#![feature(rustc_attrs)] + +trait Parser<'s> { + type Output; + + fn call(&self, input: &'s str) -> (&'s str, Self::Output); +} + +impl<'s, F, T> Parser<'s> for F +where F: Fn(&'s str) -> (&'s str, T) { + type Output = T; + fn call(&self, input: &'s str) -> (&'s str, T) { + self(input) + } +} + +fn foo( + f1: F1, + base: &'static str, + f2: F2 +) +where + F1: for<'a> Parser<'a>, + F2: FnOnce(&::Output) -> bool +{ + let s: String = base.to_owned(); + let str_ref = s.as_ref(); + let (remaining, produced) = f1.call(str_ref); + assert!(f2(&produced)); + assert_eq!(remaining.len(), 0); +} + +struct Wrapper<'a>(&'a str); + +// Because nll currently succeeds and migrate doesn't +#[rustc_error] +fn main() { + //[nll]~^ fatal + fn bar<'a>(s: &'a str) -> (&'a str, &'a str) { + (&s[..1], &s[..]) + } + + fn baz<'a>(s: &'a str) -> (&'a str, Wrapper<'a>) { + (&s[..1], Wrapper(&s[..])) + } + + foo(bar, "string", |s| s.len() == 5); + //[migrate]~^ ERROR implementation of `Parser` is not general enough + //[migrate]~| ERROR implementation of `Parser` is not general enough + //[migrate]~| ERROR implementation of `Parser` is not general enough + //[migrate]~| ERROR implementation of `Parser` is not general enough + //[migrate]~| ERROR implementation of `Parser` is not general enough + foo(baz, "string", |s| s.0.len() == 5); + //[migrate]~^ ERROR implementation of `Parser` is not general enough + //[migrate]~| ERROR implementation of `Parser` is not general enough + //[migrate]~| ERROR implementation of `Parser` is not general enough + //[migrate]~| ERROR implementation of `Parser` is not general enough + //[migrate]~| ERROR implementation of `Parser` is not general enough +} diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-74261.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-74261.rs new file mode 100644 index 0000000000000..93ccb42684c5e --- /dev/null +++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-74261.rs @@ -0,0 +1,30 @@ +// check-pass + +use std::marker::PhantomData; + +trait A<'a> { + type B; + fn b(self) -> Self::B; +} + +struct T; +struct S<'a>(PhantomData<&'a ()>); + +impl<'a> A<'a> for T { + type B = S<'a>; + fn b(self) -> Self::B { + S(PhantomData) + } +} + +fn s(t: TT, f: F) +where + TT: for<'a> A<'a>, + F: for<'a> FnOnce(>::B) +{ + f(t.b()); +} + +fn main() { + s(T, |_| {}); +} diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-76956.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-76956.rs new file mode 100644 index 0000000000000..583470080a2fc --- /dev/null +++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-76956.rs @@ -0,0 +1,15 @@ +// check-pass + +use std::ops::Deref; + +struct Data { + boxed: Box<&'static i32> +} + +impl Data { + fn use_data(&self, user: impl for <'a> FnOnce( as Deref>::Target)) { + user(*self.boxed) + } +} + +fn main() {} diff --git a/src/test/ui/issues/issue-44005.stderr b/src/test/ui/issues/issue-44005.stderr deleted file mode 100644 index 307e444e69635..0000000000000 --- a/src/test/ui/issues/issue-44005.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error[E0631]: type mismatch in closure arguments - --> $DIR/issue-44005.rs:26:5 - | -LL | uncallable(x, |y| f(y)); - | ^^^^^^^^^^ -------- found signature of `for<'r> fn(&'r i32) -> _` - | | - | expected signature of `for<'a> fn(<&i32 as Foo<'a>>::Bar) -> _` - | -note: required by a bound in `uncallable` - --> $DIR/issue-44005.rs:16:8 - | -LL | pub fn uncallable(x: T, f: F) - | ---------- required by a bound in this -... -LL | F: for<'a> Fn(>::Bar), - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `uncallable` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0631`.