From 23e45aef920e23b3add8ab8b6b7fd55f90d2d787 Mon Sep 17 00:00:00 2001 From: Jack Huey <31162821+jackh726@users.noreply.github.com> Date: Sat, 13 Nov 2021 18:45:03 -0500 Subject: [PATCH 1/6] Try to normalize associated types before processing obligations --- .../src/traits/fulfill.rs | 17 ++++ .../src/traits/project.rs | 90 ++++++++++++++++--- src/test/ui/associated-types/issue-59324.rs | 2 +- .../ui/associated-types/issue-59324.stderr | 11 ++- .../generic-associated-types/issue-90729.rs | 38 ++++++++ .../generic-associated-types/issue-93341.rs | 55 ++++++++++++ .../generic-associated-types/issue-93342.rs | 57 ++++++++++++ .../higher-rank-trait-bounds/issue-60283.rs | 4 +- .../issue-60283.stderr | 42 --------- .../normalize-under-binder/issue-62529-1.rs | 4 +- .../issue-62529-1.stderr | 52 ----------- .../issue-71955.migrate.stderr | 78 +--------------- .../issue-71955.nll.stderr | 81 +++++++++++++++-- .../normalize-under-binder/issue-71955.rs | 15 +--- .../normalize-under-binder/issue-85455.rs | 3 +- .../normalize-under-binder/issue-85455.stderr | 13 ++- .../generic_duplicate_param_use9.rs | 2 +- .../generic_duplicate_param_use9.stderr | 9 +- .../ui/type-alias-impl-trait/issue-89686.rs | 3 +- .../type-alias-impl-trait/issue-89686.stderr | 24 +---- src/test/ui/unboxed-closures/issue-53448.rs | 3 +- .../ui/unboxed-closures/issue-53448.stderr | 20 ----- 22 files changed, 364 insertions(+), 259 deletions(-) create mode 100644 src/test/ui/generic-associated-types/issue-90729.rs create mode 100644 src/test/ui/generic-associated-types/issue-93341.rs create mode 100644 src/test/ui/generic-associated-types/issue-93342.rs delete mode 100644 src/test/ui/higher-rank-trait-bounds/issue-60283.stderr delete mode 100644 src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.stderr delete mode 100644 src/test/ui/unboxed-closures/issue-53448.stderr diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 1989184f48f0e..8868468474cfb 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -346,6 +346,8 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { let obligation = &mut pending_obligation.obligation; + debug!(?obligation, "process_obligation pre-resolve"); + if obligation.predicate.has_infer_types_or_consts() { obligation.predicate = self.selcx.infcx().resolve_vars_if_possible(obligation.predicate); @@ -355,6 +357,21 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { let infcx = self.selcx.infcx(); + if obligation.predicate.has_projections() { + let mut obligations = Vec::new(); + let predicate = crate::traits::project::try_normalize_with_depth_to( + self.selcx, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth + 1, + obligation.predicate, + &mut obligations, + ); + if predicate != obligation.predicate { + obligations.push(obligation.with(predicate)); + return ProcessResult::Changed(mk_pending(obligations)); + } + } let binder = obligation.predicate.kind(); match binder.no_bound_vars() { None => match binder.skip_binder() { diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 5f338664c9a98..b1751a30b600c 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -294,6 +294,32 @@ where result } +#[instrument(level = "info", skip(selcx, param_env, cause, obligations))] +pub fn try_normalize_with_depth_to<'a, 'b, 'tcx, T>( + selcx: &'a mut SelectionContext<'b, 'tcx>, + param_env: ty::ParamEnv<'tcx>, + cause: ObligationCause<'tcx>, + depth: usize, + value: T, + obligations: &mut Vec>, +) -> T +where + T: TypeFoldable<'tcx>, +{ + debug!(obligations.len = obligations.len()); + let mut normalizer = AssocTypeNormalizer::new_without_eager_inference_replacement( + selcx, + param_env, + cause, + depth, + obligations, + ); + let result = ensure_sufficient_stack(|| normalizer.fold(value)); + debug!(?result, obligations.len = normalizer.obligations.len()); + debug!(?normalizer.obligations,); + result +} + pub(crate) fn needs_normalization<'tcx, T: TypeFoldable<'tcx>>(value: &T, reveal: Reveal) -> bool { match reveal { Reveal::UserFacing => value @@ -313,6 +339,10 @@ struct AssocTypeNormalizer<'a, 'b, 'tcx> { obligations: &'a mut Vec>, depth: usize, universes: Vec>, + /// If true, when a projection is unable to be completed, an inference + /// variable will be created and an obligation registered to project to that + /// inference variable. Also, constants will be eagerly evaluated. + eager_inference_replacement: bool, } impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> { @@ -323,7 +353,33 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> { depth: usize, obligations: &'a mut Vec>, ) -> AssocTypeNormalizer<'a, 'b, 'tcx> { - AssocTypeNormalizer { selcx, param_env, cause, obligations, depth, universes: vec![] } + AssocTypeNormalizer { + selcx, + param_env, + cause, + obligations, + depth, + universes: vec![], + eager_inference_replacement: true, + } + } + + fn new_without_eager_inference_replacement( + selcx: &'a mut SelectionContext<'b, 'tcx>, + param_env: ty::ParamEnv<'tcx>, + cause: ObligationCause<'tcx>, + depth: usize, + obligations: &'a mut Vec>, + ) -> AssocTypeNormalizer<'a, 'b, 'tcx> { + AssocTypeNormalizer { + selcx, + param_env, + cause, + obligations, + depth, + universes: vec![], + eager_inference_replacement: false, + } } fn fold>(&mut self, value: T) -> T { @@ -427,14 +483,28 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> { // there won't be bound vars there. let data = data.super_fold_with(self); - let normalized_ty = normalize_projection_type( - self.selcx, - self.param_env, - data, - self.cause.clone(), - self.depth, - &mut self.obligations, - ); + let normalized_ty = if self.eager_inference_replacement { + normalize_projection_type( + self.selcx, + self.param_env, + data, + self.cause.clone(), + self.depth, + &mut self.obligations, + ) + } else { + opt_normalize_projection_type( + self.selcx, + self.param_env, + data, + self.cause.clone(), + self.depth, + &mut self.obligations, + ) + .ok() + .flatten() + .unwrap_or_else(|| ty::Term::Ty(ty.super_fold_with(self))) + }; debug!( ?self.depth, ?ty, @@ -500,7 +570,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> { } fn fold_const(&mut self, constant: ty::Const<'tcx>) -> ty::Const<'tcx> { - if self.selcx.tcx().lazy_normalization() { + if self.selcx.tcx().lazy_normalization() || !self.eager_inference_replacement { constant } else { let constant = constant.super_fold_with(self); diff --git a/src/test/ui/associated-types/issue-59324.rs b/src/test/ui/associated-types/issue-59324.rs index 9e68e9e77515b..162f9e00edd81 100644 --- a/src/test/ui/associated-types/issue-59324.rs +++ b/src/test/ui/associated-types/issue-59324.rs @@ -15,9 +15,9 @@ pub trait ThriftService: { fn get_service( //~^ ERROR the trait bound `Bug: Foo` is not satisfied - //~| ERROR the trait bound `Bug: Foo` is not satisfied &self, ) -> Self::AssocType; + //~^ the trait bound `Bug: Foo` is not satisfied } fn with_factory(factory: dyn ThriftService<()>) {} diff --git a/src/test/ui/associated-types/issue-59324.stderr b/src/test/ui/associated-types/issue-59324.stderr index 2f430d3055e19..45d2dfb53757b 100644 --- a/src/test/ui/associated-types/issue-59324.stderr +++ b/src/test/ui/associated-types/issue-59324.stderr @@ -6,7 +6,7 @@ LL | | LL | | LL | | Service::OnlyFoo> ... | -LL | | ) -> Self::AssocType; +LL | | LL | | } | |_^ the trait `Foo` is not implemented for `Bug` | @@ -23,7 +23,7 @@ LL | | LL | | LL | | Service::OnlyFoo> ... | -LL | | ) -> Self::AssocType; +LL | | LL | | } | |_^ the trait `Foo` is not implemented for `Bug` | @@ -37,7 +37,6 @@ error[E0277]: the trait bound `Bug: Foo` is not satisfied | LL | / fn get_service( LL | | -LL | | LL | | &self, LL | | ) -> Self::AssocType; | |_________________________^ the trait `Foo` is not implemented for `Bug` @@ -48,10 +47,10 @@ LL | pub trait ThriftService: | +++++ error[E0277]: the trait bound `Bug: Foo` is not satisfied - --> $DIR/issue-59324.rs:16:8 + --> $DIR/issue-59324.rs:19:10 | -LL | fn get_service( - | ^^^^^^^^^^^ the trait `Foo` is not implemented for `Bug` +LL | ) -> Self::AssocType; + | ^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `Bug` | help: consider further restricting this bound | diff --git a/src/test/ui/generic-associated-types/issue-90729.rs b/src/test/ui/generic-associated-types/issue-90729.rs new file mode 100644 index 0000000000000..98295cce8d587 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-90729.rs @@ -0,0 +1,38 @@ +// check-pass + +#![feature(generic_associated_types)] + +use std::marker::PhantomData; + +pub trait Type { + type Ref<'a>; +} + +pub trait AsBytes {} + +impl AsBytes for &str {} + +pub struct Utf8; + +impl Type for Utf8 { + type Ref<'a> = &'a str; +} + +pub struct Bytes { + _marker: PhantomData, +} + +impl Bytes +where + for<'a> T::Ref<'a>: AsBytes, +{ + pub fn new() -> Self { + Self { + _marker: PhantomData, + } + } +} + +fn main() { + let _b = Bytes::::new(); +} diff --git a/src/test/ui/generic-associated-types/issue-93341.rs b/src/test/ui/generic-associated-types/issue-93341.rs new file mode 100644 index 0000000000000..e96a768ecda8f --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-93341.rs @@ -0,0 +1,55 @@ +// check-pass + +#![feature(generic_associated_types)] +use std::marker::PhantomData; + +pub struct Id<'id>(PhantomData &'id ()>); + +fn new_id() -> Id<'static> { + Id(PhantomData) +} + +pub trait HasLifetime where { + type AtLifetime<'a>; +} + +pub struct ExistentialLifetime(S::AtLifetime<'static>); + +impl ExistentialLifetime { + pub fn new(f: F) -> ExistentialLifetime + where for<'id> F: FnOnce(Id<'id>) -> S::AtLifetime<'id> { + ExistentialLifetime(f(new_id())) + } +} + + +struct ExampleS<'id>(Id<'id>); + +struct ExampleMarker; + +impl HasLifetime for ExampleMarker { + type AtLifetime<'id> = ExampleS<'id>; +} + + +fn broken0() -> ExistentialLifetime { + fn new_helper<'id>(id: Id<'id>) -> ExampleS<'id> { + ExampleS(id) + } + + ExistentialLifetime::::new(new_helper) +} + +fn broken1() -> ExistentialLifetime { + fn new_helper<'id>(id: Id<'id>) -> ::AtLifetime<'id> { + ExampleS(id) + } + + ExistentialLifetime::::new(new_helper) +} + +fn broken2() -> ExistentialLifetime { + ExistentialLifetime::::new(|id| ExampleS(id)) +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/issue-93342.rs b/src/test/ui/generic-associated-types/issue-93342.rs new file mode 100644 index 0000000000000..d8d7adac95161 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-93342.rs @@ -0,0 +1,57 @@ +// check-pass + +#![feature(generic_associated_types)] + +use std::marker::PhantomData; + +pub trait Scalar: 'static { + type RefType<'a>: ScalarRef<'a>; +} + +pub trait ScalarRef<'a>: 'a {} + +impl Scalar for i32 { + type RefType<'a> = i32; +} + +impl Scalar for String { + type RefType<'a> = &'a str; +} + +impl Scalar for bool { + type RefType<'a> = i32; +} + +impl<'a> ScalarRef<'a> for bool {} + +impl<'a> ScalarRef<'a> for i32 {} + +impl<'a> ScalarRef<'a> for &'a str {} + +fn str_contains(a: &str, b: &str) -> bool { + a.contains(b) +} + +pub struct BinaryExpression +where + F: Fn(A::RefType<'_>, B::RefType<'_>) -> O, +{ + f: F, + _phantom: PhantomData<(A, B, O)>, +} + +impl BinaryExpression +where + F: Fn(A::RefType<'_>, B::RefType<'_>) -> O, +{ + pub fn new(f: F) -> Self { + Self { + f, + _phantom: PhantomData, + } + } +} + +fn main() { + BinaryExpression::::new(str_contains); +} diff --git a/src/test/ui/higher-rank-trait-bounds/issue-60283.rs b/src/test/ui/higher-rank-trait-bounds/issue-60283.rs index c63b1544a5379..05315b3f9f5e9 100644 --- a/src/test/ui/higher-rank-trait-bounds/issue-60283.rs +++ b/src/test/ui/higher-rank-trait-bounds/issue-60283.rs @@ -1,3 +1,5 @@ +// check-pass + pub trait Trait<'a> { type Item; } @@ -15,6 +17,4 @@ where fn main() { foo((), drop) - //~^ ERROR type mismatch in function arguments - //~| ERROR size for values of type `<() as Trait<'_>>::Item` cannot be known at compilation time } diff --git a/src/test/ui/higher-rank-trait-bounds/issue-60283.stderr b/src/test/ui/higher-rank-trait-bounds/issue-60283.stderr deleted file mode 100644 index 34893cd8f19d9..0000000000000 --- a/src/test/ui/higher-rank-trait-bounds/issue-60283.stderr +++ /dev/null @@ -1,42 +0,0 @@ -error[E0631]: type mismatch in function arguments - --> $DIR/issue-60283.rs:17:13 - | -LL | foo((), drop) - | --- ^^^^ - | | | - | | expected signature of `for<'a> fn(<() as Trait<'a>>::Item) -> _` - | | found signature of `fn(()) -> _` - | required by a bound introduced by this call - | -note: required by a bound in `foo` - --> $DIR/issue-60283.rs:12:16 - | -LL | pub fn foo(_: T, _: F) - | --- required by a bound in this -... -LL | F: for<'a> FnMut(>::Item), - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `foo` - -error[E0277]: the size for values of type `<() as Trait<'_>>::Item` cannot be known at compilation time - --> $DIR/issue-60283.rs:17:13 - | -LL | foo((), drop) - | --- ^^^^ doesn't have a size known at compile-time - | | - | required by a bound introduced by this call - | - = help: the trait `Sized` is not implemented for `<() as Trait<'_>>::Item` -note: required by a bound in `std::mem::drop` - --> $SRC_DIR/core/src/mem/mod.rs:LL:COL - | -LL | pub fn drop(_x: T) {} - | ^ required by this bound in `std::mem::drop` -help: consider further restricting the associated type - | -LL | fn main() where <() as Trait<'_>>::Item: Sized { - | ++++++++++++++++++++++++++++++++++++ - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0277, E0631. -For more information about an error, try `rustc --explain E0277`. 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 7c3c72e04cb78..c6f29fa59085d 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 @@ -1,3 +1,5 @@ +// check-pass + // FamilyType (GAT workaround) pub trait FamilyLt<'a> { type Out; @@ -78,8 +80,6 @@ where P: Execute + 'static { fn main() { task(annotate( - //~^ the size - //~^^ the trait bound Annotate::>::new(), |value: &mut usize| { *value = 2; 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 deleted file mode 100644 index 01b14660b6531..0000000000000 --- a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.stderr +++ /dev/null @@ -1,52 +0,0 @@ -error[E0277]: the size for values of type `impl Execute` cannot be known at compilation time - --> $DIR/issue-62529-1.rs:80:10 - | -LL | task(annotate( - | _____----_^ - | | | - | | required by a bound introduced by this call -LL | | -LL | | -LL | | Annotate::>::new(), -... | -LL | | } -LL | | )); - | |_____^ doesn't have a size known at compile-time - | - = help: the trait `Sized` is not implemented for `impl Execute` -note: required by a bound in `task` - --> $DIR/issue-62529-1.rs:69:9 - | -LL | fn task

(processor: P) -> Task - | ^ required by this bound in `task` -help: consider relaxing the implicit `Sized` restriction - | -LL | fn task(processor: P) -> Task - | ++++++++ - -error[E0277]: the trait bound `impl Execute: Execute` is not satisfied - --> $DIR/issue-62529-1.rs:80:10 - | -LL | task(annotate( - | _____----_^ - | | | - | | required by a bound introduced by this call -LL | | -LL | | -LL | | Annotate::>::new(), -... | -LL | | } -LL | | )); - | |_____^ the trait `Execute` is not implemented for `impl Execute` - | -note: required by a bound in `task` - --> $DIR/issue-62529-1.rs:70:10 - | -LL | fn task

(processor: P) -> Task - | ---- required by a bound in this -LL | where P: Execute + 'static { - | ^^^^^^^ required by this bound in `task` - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0277`. 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 index 7da6b029c26f0..e6ffe38ee92e8 100644 --- 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 @@ -1,5 +1,5 @@ error: implementation of `Parser` is not general enough - --> $DIR/issue-71955.rs:57:5 + --> $DIR/issue-71955.rs:54:5 | LL | foo(bar, "string", |s| s.len() == 5); | ^^^ implementation of `Parser` is not general enough @@ -8,79 +8,7 @@ LL | foo(bar, "string", |s| s.len() == 5); = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1` error: implementation of `Parser` is not general enough - --> $DIR/issue-71955.rs:57: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:57: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:57: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:57: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:63: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:63: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:63: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:63: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:63:5 + --> $DIR/issue-71955.rs:58:5 | LL | foo(baz, "string", |s| s.0.len() == 5); | ^^^ implementation of `Parser` is not general enough @@ -88,5 +16,5 @@ LL | foo(baz, "string", |s| s.0.len() == 5); = 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 +error: aborting due to 2 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 index c2feaa9128055..0f38f8e3283a2 100644 --- 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 @@ -1,8 +1,79 @@ -error: fatal error triggered by #[rustc_error] - --> $DIR/issue-71955.rs:47:1 +error[E0308]: mismatched types + --> $DIR/issue-71955.rs:54:5 | -LL | fn main() { - | ^^^^^^^^^ +LL | foo(bar, "string", |s| s.len() == 5); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected type `for<'r, 's> FnOnce<(&'r &'s str,)>` + found type `for<'r> FnOnce<(&'r &str,)>` +note: this closure does not fulfill the lifetime requirements + --> $DIR/issue-71955.rs:54:24 + | +LL | foo(bar, "string", |s| s.len() == 5); + | ^^^^^^^^^^^^^^^^ +note: the lifetime requirement is introduced here + --> $DIR/issue-71955.rs:34:9 + | +LL | F2: FnOnce(&::Output) -> bool + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/issue-71955.rs:54:5 + | +LL | foo(bar, "string", |s| s.len() == 5); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected type `FnOnce<(&&str,)>` + found type `for<'r> FnOnce<(&'r &str,)>` +note: this closure does not fulfill the lifetime requirements + --> $DIR/issue-71955.rs:54:24 + | +LL | foo(bar, "string", |s| s.len() == 5); + | ^^^^^^^^^^^^^^^^ +note: the lifetime requirement is introduced here + --> $DIR/issue-71955.rs:34:44 + | +LL | F2: FnOnce(&::Output) -> bool + | ^^^^ + +error[E0308]: mismatched types + --> $DIR/issue-71955.rs:58:5 + | +LL | foo(baz, "string", |s| s.0.len() == 5); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected type `for<'r, 's> FnOnce<(&'r Wrapper<'s>,)>` + found type `for<'r> FnOnce<(&'r Wrapper<'_>,)>` +note: this closure does not fulfill the lifetime requirements + --> $DIR/issue-71955.rs:58:24 + | +LL | foo(baz, "string", |s| s.0.len() == 5); + | ^^^^^^^^^^^^^^^^^^ +note: the lifetime requirement is introduced here + --> $DIR/issue-71955.rs:34:9 + | +LL | F2: FnOnce(&::Output) -> bool + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/issue-71955.rs:58:5 + | +LL | foo(baz, "string", |s| s.0.len() == 5); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected type `FnOnce<(&Wrapper<'_>,)>` + found type `for<'r> FnOnce<(&'r Wrapper<'_>,)>` +note: this closure does not fulfill the lifetime requirements + --> $DIR/issue-71955.rs:58:24 + | +LL | foo(baz, "string", |s| s.0.len() == 5); + | ^^^^^^^^^^^^^^^^^^ +note: the lifetime requirement is introduced here + --> $DIR/issue-71955.rs:34:44 + | +LL | F2: FnOnce(&::Output) -> bool + | ^^^^ -error: aborting due to previous error +error: aborting due to 4 previous errors +For more information about this error, try `rustc --explain E0308`. 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 index 3d6778b6942c5..4b7e207b96d49 100644 --- 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 @@ -42,10 +42,7 @@ where 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[..]) } @@ -56,14 +53,10 @@ fn main() { 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 + //[nll]~^^ ERROR mismatched types + //[nll]~| ERROR mismatched types 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 + //[nll]~^^ ERROR mismatched types + //[nll]~| ERROR mismatched types } diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.rs index 3a4d6c02a159f..fe319e6c8515c 100644 --- a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.rs +++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.rs @@ -6,7 +6,8 @@ trait SomeTrait<'a> { fn give_me_ice() { callee:: >::Associated>(); - //~^ ERROR: the trait bound `T: SomeTrait<'_>` is not satisfied + //~^ ERROR the trait bound `T: SomeTrait<'_>` is not satisfied [E0277] + //~| ERROR the trait bound `T: SomeTrait<'_>` is not satisfied [E0277] } fn callee>() { diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.stderr b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.stderr index aaf45dc7ad564..13b68b072403a 100644 --- a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.stderr +++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.stderr @@ -9,6 +9,17 @@ help: consider restricting type parameter `T` LL | fn give_me_ice>() { | +++++++++++++++ -error: aborting due to previous error +error[E0277]: the trait bound `T: SomeTrait<'_>` is not satisfied + --> $DIR/issue-85455.rs:8:14 + | +LL | callee:: >::Associated>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `SomeTrait<'_>` is not implemented for `T` + | +help: consider restricting type parameter `T` + | +LL | fn give_me_ice>() { + | +++++++++++++++ + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.rs index 747081933172b..4baf198b12fae 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.rs +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.rs @@ -5,7 +5,7 @@ use std::fmt::Debug; fn main() {} type Two = impl Debug; -//~^ ERROR the trait bound `A: Foo` is not satisfied in `(A, B, ::Bar)` +//~^ ERROR the trait bound `A: Foo` is not satisfied //~| ERROR `A` doesn't implement `Debug` //~| ERROR `B` doesn't implement `Debug` diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr index a8eb53a50e38b..43471f980b2af 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr @@ -10,13 +10,12 @@ note: previous use here LL | fn two(t: T, u: U) -> Two { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0277]: the trait bound `A: Foo` is not satisfied in `(A, B, ::Bar)` +error[E0277]: the trait bound `A: Foo` is not satisfied --> $DIR/generic_duplicate_param_use9.rs:7:18 | LL | type Two = impl Debug; - | ^^^^^^^^^^ within `(A, B, ::Bar)`, the trait `Foo` is not implemented for `A` + | ^^^^^^^^^^ the trait `Foo` is not implemented for `A` | - = note: required because it appears within the type `(A, B, ::Bar)` help: consider restricting type parameter `A` | LL | type Two = impl Debug; @@ -28,7 +27,7 @@ error[E0277]: `A` doesn't implement `Debug` LL | type Two = impl Debug; | ^^^^^^^^^^ `A` cannot be formatted using `{:?}` because it doesn't implement `Debug` | - = note: required because of the requirements on the impl of `Debug` for `(A, B, ::Bar)` + = note: required because of the requirements on the impl of `Debug` for `(A, B, _)` help: consider restricting type parameter `A` | LL | type Two = impl Debug; @@ -40,7 +39,7 @@ error[E0277]: `B` doesn't implement `Debug` LL | type Two = impl Debug; | ^^^^^^^^^^ `B` cannot be formatted using `{:?}` because it doesn't implement `Debug` | - = note: required because of the requirements on the impl of `Debug` for `(A, B, ::Bar)` + = note: required because of the requirements on the impl of `Debug` for `(A, B, _)` help: consider restricting type parameter `B` | LL | type Two = impl Debug; diff --git a/src/test/ui/type-alias-impl-trait/issue-89686.rs b/src/test/ui/type-alias-impl-trait/issue-89686.rs index 5878b26fddbc7..f058653dde338 100644 --- a/src/test/ui/type-alias-impl-trait/issue-89686.rs +++ b/src/test/ui/type-alias-impl-trait/issue-89686.rs @@ -5,8 +5,7 @@ use std::future::Future; type G<'a, T> = impl Future; -//~^ ERROR: type mismatch resolving ` as Future>::Output == ()` -//~| ERROR: the trait bound `T: Trait` is not satisfied +//~^ ERROR: the trait bound `T: Trait` is not satisfied trait Trait { type F: Future; diff --git a/src/test/ui/type-alias-impl-trait/issue-89686.stderr b/src/test/ui/type-alias-impl-trait/issue-89686.stderr index 19ed9a7476c1b..0df5a809ebb47 100644 --- a/src/test/ui/type-alias-impl-trait/issue-89686.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-89686.stderr @@ -1,22 +1,3 @@ -error[E0271]: type mismatch resolving ` as Future>::Output == ()` - --> $DIR/issue-89686.rs:7:17 - | -LL | type G<'a, T> = impl Future; - | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found associated type -... -LL | async move { self.f().await } - | ------------------ the found `async` block - | - ::: $SRC_DIR/core/src/future/mod.rs:LL:COL - | -LL | pub const fn from_generator(gen: T) -> impl Future - | ------------------------------- the found opaque type - | - = note: expected unit type `()` - found associated type ` as Future>::Output` - = help: consider constraining the associated type ` as Future>::Output` to `()` - = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html - error[E0277]: the trait bound `T: Trait` is not satisfied --> $DIR/issue-89686.rs:7:17 | @@ -28,7 +9,6 @@ help: consider restricting type parameter `T` LL | type G<'a, T: Trait> = impl Future; | +++++++ -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0271, E0277. -For more information about an error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/unboxed-closures/issue-53448.rs b/src/test/ui/unboxed-closures/issue-53448.rs index 5c82a56e77e14..ea1edf7d45073 100644 --- a/src/test/ui/unboxed-closures/issue-53448.rs +++ b/src/test/ui/unboxed-closures/issue-53448.rs @@ -1,3 +1,5 @@ +// check-pass + #![feature(unboxed_closures)] trait Lt<'a> { @@ -10,6 +12,5 @@ impl<'a> Lt<'a> for () { fn main() { let v: <() as Lt<'_>>::T = (); let f: &mut dyn FnMut<(_,), Output = ()> = &mut |_: <() as Lt<'_>>::T| {}; - //~^ ERROR: the size for values of type `<() as Lt<'_>>::T` cannot be known f(v); } diff --git a/src/test/ui/unboxed-closures/issue-53448.stderr b/src/test/ui/unboxed-closures/issue-53448.stderr deleted file mode 100644 index 8f9d918fdba2b..0000000000000 --- a/src/test/ui/unboxed-closures/issue-53448.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error[E0277]: the size for values of type `<() as Lt<'_>>::T` cannot be known at compilation time - --> $DIR/issue-53448.rs:12:54 - | -LL | let f: &mut dyn FnMut<(_,), Output = ()> = &mut |_: <() as Lt<'_>>::T| {}; - | ^ doesn't have a size known at compile-time - | - = help: the trait `Sized` is not implemented for `<() as Lt<'_>>::T` - = help: unsized fn params are gated as an unstable feature -help: consider further restricting the associated type - | -LL | fn main() where <() as Lt<'_>>::T: Sized { - | ++++++++++++++++++++++++++++++ -help: function arguments must have a statically known size, borrowed types always have a known size - | -LL | let f: &mut dyn FnMut<(_,), Output = ()> = &mut |_: &<() as Lt<'_>>::T| {}; - | + - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0277`. From 87a37788acd667cbf0207ce50cb8a62975674727 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 15 Feb 2022 12:56:23 -0800 Subject: [PATCH 2/6] bless tests since rebase --- .../ui/generic-associated-types/bugs/issue-88382.stderr | 8 ++++---- src/test/ui/generic-associated-types/issue-91139.rs | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/test/ui/generic-associated-types/bugs/issue-88382.stderr b/src/test/ui/generic-associated-types/bugs/issue-88382.stderr index 05bc58cbba4e6..acb2eb8a84d46 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-88382.stderr +++ b/src/test/ui/generic-associated-types/bugs/issue-88382.stderr @@ -2,18 +2,18 @@ error[E0631]: type mismatch in function arguments --> $DIR/issue-88382.rs:27:40 | LL | do_something(SomeImplementation(), test); - | ------------ ^^^^ expected signature of `for<'a> fn(&mut ::Iterator<'a>) -> _` + | ------------ ^^^^ expected signature of `for<'r> fn(&'r mut std::iter::Empty) -> _` | | | required by a bound introduced by this call ... LL | fn test<'a, I: Iterable>(_: &mut I::Iterator<'a>) {} - | ------------------------------------------------- found signature of `for<'r> fn(&'r mut std::iter::Empty) -> _` + | ------------------------------------------------- found signature of `for<'r, 'a> fn(&'r mut <_ as Iterable>::Iterator<'a>) -> _` | note: required by a bound in `do_something` - --> $DIR/issue-88382.rs:21:56 + --> $DIR/issue-88382.rs:21:48 | LL | fn do_something(i: I, mut f: impl for<'a> Fn(&mut I::Iterator<'a>)) { - | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `do_something` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `do_something` error: aborting due to previous error diff --git a/src/test/ui/generic-associated-types/issue-91139.rs b/src/test/ui/generic-associated-types/issue-91139.rs index 2b82d2946b3ba..2a7a962b25241 100644 --- a/src/test/ui/generic-associated-types/issue-91139.rs +++ b/src/test/ui/generic-associated-types/issue-91139.rs @@ -15,7 +15,7 @@ impl Foo for () { = (); } -fn foo() { +fn foo() { let _: for<'a> fn(<() as Foo>::Type<'a>, &'a T) = |_, _| (); } From 2c13e4a25a2e917a220918424be96a78ff06858f Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 15 Feb 2022 13:28:16 -0800 Subject: [PATCH 3/6] only normalize projections if they have inference variables in them --- compiler/rustc_middle/src/ty/flags.rs | 6 ++++++ compiler/rustc_middle/src/ty/fold.rs | 8 ++++++++ compiler/rustc_trait_selection/src/traits/fulfill.rs | 2 +- compiler/rustc_type_ir/src/lib.rs | 3 +++ 4 files changed, 18 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index 948a48c082644..0bc3bdfbeac3f 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -327,7 +327,13 @@ impl FlagComputation { } fn add_projection_ty(&mut self, projection_ty: ty::ProjectionTy<'_>) { + let old_outer_exclusive_binder = + std::mem::replace(&mut self.outer_exclusive_binder, ty::INNERMOST); self.add_substs(projection_ty.substs); + if self.outer_exclusive_binder > ty::INNERMOST { + self.add_flags(TypeFlags::HAS_LATE_IN_PROJECTION); + } + self.outer_exclusive_binder = self.outer_exclusive_binder.max(old_outer_exclusive_binder); } fn add_substs(&mut self, substs: &[GenericArg<'_>]) { diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index b3006672e2220..d3559e9833bc1 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -166,6 +166,14 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone { fn still_further_specializable(&self) -> bool { self.has_type_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE) } + + // Indicates that this value has projection types which capture late-bound variables, + // which is a sign that the projection types within need further normalization. This + // is because we do not replace projections with inference variables when they capture + // late-bound variables. + fn has_late_bound_vars_in_projection(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_LATE_IN_PROJECTION) + } } impl<'tcx> TypeFoldable<'tcx> for hir::Constness { diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 8868468474cfb..4d11dfe2859ab 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -357,7 +357,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { let infcx = self.selcx.infcx(); - if obligation.predicate.has_projections() { + if obligation.predicate.has_late_bound_vars_in_projection() { let mut obligations = Vec::new(); let predicate = crate::traits::project::try_normalize_with_depth_to( self.selcx, diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index ec6fb622d32aa..797f728c53309 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -107,6 +107,9 @@ bitflags! { /// Does this value have `InferConst::Fresh`? const HAS_CT_FRESH = 1 << 19; + + // Does this value have any late-bound vars in any projection type substs? + const HAS_LATE_IN_PROJECTION = 1 << 20; } } From a201e6738639f85379f17d657ceefb70e3bd8a56 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 26 Jan 2022 21:47:03 -0800 Subject: [PATCH 4/6] Normalize possibly un-normalized GAT projections --- .../rustc_infer/src/infer/type_variable.rs | 2 +- .../src/traits/select/confirmation.rs | 103 +++++------------- 2 files changed, 31 insertions(+), 74 deletions(-) diff --git a/compiler/rustc_infer/src/infer/type_variable.rs b/compiler/rustc_infer/src/infer/type_variable.rs index d320728a43f95..c3a6cdd23a4f7 100644 --- a/compiler/rustc_infer/src/infer/type_variable.rs +++ b/compiler/rustc_infer/src/infer/type_variable.rs @@ -263,7 +263,7 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> { let index = self.values().push(TypeVariableData { origin }); assert_eq!(eq_key.vid.as_u32(), index as u32); - debug!("new_var(index={:?}, universe={:?}, origin={:?}", eq_key.vid, universe, origin,); + debug!("new_var(index={:?}, universe={:?}, origin={:?})", eq_key.vid, universe, origin); eq_key.vid } diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 84bc7cdff2890..2579e4b317434 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -553,23 +553,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) .map_bound(|(trait_ref, _)| trait_ref); - 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, - ) - }); - - obligations.extend(self.confirm_poly_trait_refs( - obligation.cause.clone(), - obligation.param_env, - obligation.predicate.to_poly_trait_ref(), - trait_ref, - )?); - Ok(ImplSourceFnPointerData { fn_ty: self_ty, nested: obligations }) + let nested = self.confirm_poly_trait_refs(obligation, trait_ref)?; + Ok(ImplSourceFnPointerData { fn_ty: self_ty, nested }) } fn confirm_trait_alias_candidate( @@ -616,26 +601,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { debug!(?obligation, ?generator_def_id, ?substs, "confirm_generator_candidate"); let trait_ref = self.generator_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, - ) - }); - debug!(?trait_ref, ?obligations, "generator candidate obligations"); - - obligations.extend(self.confirm_poly_trait_refs( - obligation.cause.clone(), - obligation.param_env, - obligation.predicate.to_poly_trait_ref(), - trait_ref, - )?); + let nested = self.confirm_poly_trait_refs(obligation, trait_ref)?; + debug!(?trait_ref, ?nested, "generator candidate obligations"); - Ok(ImplSourceGeneratorData { generator_def_id, substs, nested: obligations }) + Ok(ImplSourceGeneratorData { generator_def_id, substs, nested }) } #[instrument(skip(self), level = "debug")] @@ -657,44 +627,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { _ => bug!("closure candidate for non-closure {:?}", obligation), }; - let obligation_predicate = obligation.predicate; - 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, obligations: trait_ref_obligations } = - ensure_sufficient_stack(|| { - normalize_with_depth( - self, - obligation.param_env, - obligation.cause.clone(), - obligation.recursion_depth + 1, - trait_ref, - ) - }); + let mut nested = self.confirm_poly_trait_refs(obligation, 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(), - trait_ref, - )?); + debug!(?closure_def_id, ?trait_ref, ?nested, "confirm closure candidate obligations"); // FIXME: Chalk if !self.tcx().sess.opts.debugging_opts.chalk { - obligations.push(Obligation::new( + nested.push(Obligation::new( obligation.cause.clone(), obligation.param_env, ty::Binder::dummy(ty::PredicateKind::ClosureKind(closure_def_id, substs, kind)) @@ -702,7 +643,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { )); } - Ok(ImplSourceClosureData { closure_def_id, substs, nested: obligations }) + Ok(ImplSourceClosureData { closure_def_id, substs, nested }) } /// In the case of closure types and fn pointers, @@ -733,15 +674,31 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { #[instrument(skip(self), level = "trace")] fn confirm_poly_trait_refs( &mut self, - obligation_cause: ObligationCause<'tcx>, - obligation_param_env: ty::ParamEnv<'tcx>, - obligation_trait_ref: ty::PolyTraitRef<'tcx>, + obligation: &TraitObligation<'tcx>, expected_trait_ref: ty::PolyTraitRef<'tcx>, ) -> Result>, SelectionError<'tcx>> { + let obligation_trait_ref = obligation.predicate.to_poly_trait_ref(); + // Normalize the obligation and expected trait refs together, because why not + let Normalized { obligations: nested, value: (obligation_trait_ref, expected_trait_ref) } = + ensure_sufficient_stack(|| { + self.infcx.commit_unconditionally(|_| { + normalize_with_depth( + self, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth + 1, + (obligation_trait_ref, expected_trait_ref), + ) + }) + }); + self.infcx - .at(&obligation_cause, obligation_param_env) + .at(&obligation.cause, obligation.param_env) .sup(obligation_trait_ref, expected_trait_ref) - .map(|InferOk { obligations, .. }| obligations) + .map(|InferOk { mut obligations, .. }| { + obligations.extend(nested); + obligations + }) .map_err(|e| OutputTypeParameterMismatch(expected_trait_ref, obligation_trait_ref, e)) } From 7a0f2e0c58177dbfc68c9fc7c6df3bd2ac1ba6ae Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 15 Feb 2022 19:33:19 -0800 Subject: [PATCH 5/6] wip --- .../rustc_typeck/src/check/fn_ctxt/_impl.rs | 7 +++++- src/test/ui/associated-types/issue-59324.rs | 4 ++-- .../ui/associated-types/issue-59324.stderr | 13 +++++----- .../generic_duplicate_param_use9.stderr | 9 +++---- .../ui/type-alias-impl-trait/issue-89686.rs | 1 + .../type-alias-impl-trait/issue-89686.stderr | 24 +++++++++++++++++-- 6 files changed, 43 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index 96bbc2800d50a..9299c87db0eeb 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -447,7 +447,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) { if !ty.references_error() { let lang_item = self.tcx.require_lang_item(LangItem::Sized, None); - self.require_type_meets(ty, span, code, lang_item); + self.require_type_meets( + self.normalize_associated_types_in(span, ty), + span, + code, + lang_item, + ); } } diff --git a/src/test/ui/associated-types/issue-59324.rs b/src/test/ui/associated-types/issue-59324.rs index 162f9e00edd81..e7266cfdf8dd8 100644 --- a/src/test/ui/associated-types/issue-59324.rs +++ b/src/test/ui/associated-types/issue-59324.rs @@ -15,9 +15,9 @@ pub trait ThriftService: { fn get_service( //~^ ERROR the trait bound `Bug: Foo` is not satisfied - &self, + //~| ERROR the trait bound `Bug: Foo` is not satisfied + &self, ) -> Self::AssocType; - //~^ the trait bound `Bug: Foo` is not satisfied } fn with_factory(factory: dyn ThriftService<()>) {} diff --git a/src/test/ui/associated-types/issue-59324.stderr b/src/test/ui/associated-types/issue-59324.stderr index 45d2dfb53757b..461b20cfbdd6c 100644 --- a/src/test/ui/associated-types/issue-59324.stderr +++ b/src/test/ui/associated-types/issue-59324.stderr @@ -6,7 +6,7 @@ LL | | LL | | LL | | Service::OnlyFoo> ... | -LL | | +LL | | ) -> Self::AssocType; LL | | } | |_^ the trait `Foo` is not implemented for `Bug` | @@ -23,7 +23,7 @@ LL | | LL | | LL | | Service::OnlyFoo> ... | -LL | | +LL | | ) -> Self::AssocType; LL | | } | |_^ the trait `Foo` is not implemented for `Bug` | @@ -37,7 +37,8 @@ error[E0277]: the trait bound `Bug: Foo` is not satisfied | LL | / fn get_service( LL | | -LL | | &self, +LL | | +LL | | &self, LL | | ) -> Self::AssocType; | |_________________________^ the trait `Foo` is not implemented for `Bug` | @@ -47,10 +48,10 @@ LL | pub trait ThriftService: | +++++ error[E0277]: the trait bound `Bug: Foo` is not satisfied - --> $DIR/issue-59324.rs:19:10 + --> $DIR/issue-59324.rs:16:8 | -LL | ) -> Self::AssocType; - | ^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `Bug` +LL | fn get_service( + | ^^^^^^^^^^^ the trait `Foo` is not implemented for `Bug` | help: consider further restricting this bound | diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr index 43471f980b2af..a8eb53a50e38b 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr @@ -10,12 +10,13 @@ note: previous use here LL | fn two(t: T, u: U) -> Two { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0277]: the trait bound `A: Foo` is not satisfied +error[E0277]: the trait bound `A: Foo` is not satisfied in `(A, B, ::Bar)` --> $DIR/generic_duplicate_param_use9.rs:7:18 | LL | type Two = impl Debug; - | ^^^^^^^^^^ the trait `Foo` is not implemented for `A` + | ^^^^^^^^^^ within `(A, B, ::Bar)`, the trait `Foo` is not implemented for `A` | + = note: required because it appears within the type `(A, B, ::Bar)` help: consider restricting type parameter `A` | LL | type Two = impl Debug; @@ -27,7 +28,7 @@ error[E0277]: `A` doesn't implement `Debug` LL | type Two = impl Debug; | ^^^^^^^^^^ `A` cannot be formatted using `{:?}` because it doesn't implement `Debug` | - = note: required because of the requirements on the impl of `Debug` for `(A, B, _)` + = note: required because of the requirements on the impl of `Debug` for `(A, B, ::Bar)` help: consider restricting type parameter `A` | LL | type Two = impl Debug; @@ -39,7 +40,7 @@ error[E0277]: `B` doesn't implement `Debug` LL | type Two = impl Debug; | ^^^^^^^^^^ `B` cannot be formatted using `{:?}` because it doesn't implement `Debug` | - = note: required because of the requirements on the impl of `Debug` for `(A, B, _)` + = note: required because of the requirements on the impl of `Debug` for `(A, B, ::Bar)` help: consider restricting type parameter `B` | LL | type Two = impl Debug; diff --git a/src/test/ui/type-alias-impl-trait/issue-89686.rs b/src/test/ui/type-alias-impl-trait/issue-89686.rs index f058653dde338..6fd5df619e201 100644 --- a/src/test/ui/type-alias-impl-trait/issue-89686.rs +++ b/src/test/ui/type-alias-impl-trait/issue-89686.rs @@ -6,6 +6,7 @@ use std::future::Future; type G<'a, T> = impl Future; //~^ ERROR: the trait bound `T: Trait` is not satisfied +//~| ERROR type mismatch resolving ` as Future>::Output == ()` trait Trait { type F: Future; diff --git a/src/test/ui/type-alias-impl-trait/issue-89686.stderr b/src/test/ui/type-alias-impl-trait/issue-89686.stderr index 0df5a809ebb47..19ed9a7476c1b 100644 --- a/src/test/ui/type-alias-impl-trait/issue-89686.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-89686.stderr @@ -1,3 +1,22 @@ +error[E0271]: type mismatch resolving ` as Future>::Output == ()` + --> $DIR/issue-89686.rs:7:17 + | +LL | type G<'a, T> = impl Future; + | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found associated type +... +LL | async move { self.f().await } + | ------------------ the found `async` block + | + ::: $SRC_DIR/core/src/future/mod.rs:LL:COL + | +LL | pub const fn from_generator(gen: T) -> impl Future + | ------------------------------- the found opaque type + | + = note: expected unit type `()` + found associated type ` as Future>::Output` + = help: consider constraining the associated type ` as Future>::Output` to `()` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html + error[E0277]: the trait bound `T: Trait` is not satisfied --> $DIR/issue-89686.rs:7:17 | @@ -9,6 +28,7 @@ help: consider restricting type parameter `T` LL | type G<'a, T: Trait> = impl Future; | +++++++ -error: aborting due to previous error +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0271, E0277. +For more information about an error, try `rustc --explain E0271`. From 82d188211d2cd089858adbc727904500ba0b20c2 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 15 Feb 2022 19:57:55 -0800 Subject: [PATCH 6/6] don't resolve type variables twice --- .../src/traits/fulfill.rs | 34 ++++++------- .../normalize-under-binder/issue-85455.rs | 1 - .../normalize-under-binder/issue-85455.stderr | 13 +---- src/test/ui/hrtb/issue-62203-hrtb-ice.stderr | 48 +++++++++---------- 4 files changed, 42 insertions(+), 54 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 4d11dfe2859ab..9d83049ba1998 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -347,31 +347,31 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { let obligation = &mut pending_obligation.obligation; debug!(?obligation, "process_obligation pre-resolve"); + let infcx = self.selcx.infcx(); if obligation.predicate.has_infer_types_or_consts() { + if obligation.predicate.has_late_bound_vars_in_projection() { + let mut obligations = Vec::new(); + let predicate = crate::traits::project::try_normalize_with_depth_to( + self.selcx, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth + 1, + obligation.predicate, + &mut obligations, + ); + if predicate != obligation.predicate { + obligations.push(obligation.with(predicate)); + return ProcessResult::Changed(mk_pending(obligations)); + } + } + obligation.predicate = self.selcx.infcx().resolve_vars_if_possible(obligation.predicate); } debug!(?obligation, ?obligation.cause, "process_obligation"); - let infcx = self.selcx.infcx(); - - if obligation.predicate.has_late_bound_vars_in_projection() { - let mut obligations = Vec::new(); - let predicate = crate::traits::project::try_normalize_with_depth_to( - self.selcx, - obligation.param_env, - obligation.cause.clone(), - obligation.recursion_depth + 1, - obligation.predicate, - &mut obligations, - ); - if predicate != obligation.predicate { - obligations.push(obligation.with(predicate)); - return ProcessResult::Changed(mk_pending(obligations)); - } - } let binder = obligation.predicate.kind(); match binder.no_bound_vars() { None => match binder.skip_binder() { diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.rs index fe319e6c8515c..8dc3895366489 100644 --- a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.rs +++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.rs @@ -7,7 +7,6 @@ trait SomeTrait<'a> { fn give_me_ice() { callee:: >::Associated>(); //~^ ERROR the trait bound `T: SomeTrait<'_>` is not satisfied [E0277] - //~| ERROR the trait bound `T: SomeTrait<'_>` is not satisfied [E0277] } fn callee>() { diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.stderr b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.stderr index 13b68b072403a..aaf45dc7ad564 100644 --- a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.stderr +++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.stderr @@ -9,17 +9,6 @@ help: consider restricting type parameter `T` LL | fn give_me_ice>() { | +++++++++++++++ -error[E0277]: the trait bound `T: SomeTrait<'_>` is not satisfied - --> $DIR/issue-85455.rs:8:14 - | -LL | callee:: >::Associated>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `SomeTrait<'_>` is not implemented for `T` - | -help: consider restricting type parameter `T` - | -LL | fn give_me_ice>() { - | +++++++++++++++ - -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/hrtb/issue-62203-hrtb-ice.stderr b/src/test/ui/hrtb/issue-62203-hrtb-ice.stderr index 0ebba37e4ec70..af7d9c18d59ef 100644 --- a/src/test/ui/hrtb/issue-62203-hrtb-ice.stderr +++ b/src/test/ui/hrtb/issue-62203-hrtb-ice.stderr @@ -1,27 +1,3 @@ -error[E0271]: type mismatch resolving `for<'r> as T0<'r, (&'r u8,)>>::O == <_ as Ty<'r>>::V` - --> $DIR/issue-62203-hrtb-ice.rs:38:19 - | -LL | let v = Unit2.m( - | ^ type mismatch resolving `for<'r> as T0<'r, (&'r u8,)>>::O == <_ as Ty<'r>>::V` - | -note: expected this to be `<_ as Ty<'_>>::V` - --> $DIR/issue-62203-hrtb-ice.rs:21:14 - | -LL | type O = T::Output; - | ^^^^^^^^^ - = note: expected associated type `<_ as Ty<'_>>::V` - found struct `Unit4` - = help: consider constraining the associated type `<_ as Ty<'_>>::V` to `Unit4` or calling a method that returns `<_ as Ty<'_>>::V` - = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html -note: required by a bound in `T1::m` - --> $DIR/issue-62203-hrtb-ice.rs:27:51 - | -LL | fn m<'a, B: Ty<'a>, F>(&self, f: F) -> Unit1 - | - required by a bound in this -LL | where -LL | F: for<'r> T0<'r, (>::V,), O = >::V>, - | ^^^^^^^^^^^^^^^^^^^^ required by this bound in `T1::m` - error[E0271]: type mismatch resolving `for<'r> <[closure@$DIR/issue-62203-hrtb-ice.rs:42:17: 42:39] as FnOnce<((&'r u8,),)>>::Output == Unit3` --> $DIR/issue-62203-hrtb-ice.rs:40:9 | @@ -48,6 +24,30 @@ LL | where LL | F: for<'r> T0<'r, (>::V,), O = >::V>, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `T1::m` +error[E0271]: type mismatch resolving `for<'r> as T0<'r, (&'r u8,)>>::O == <_ as Ty<'r>>::V` + --> $DIR/issue-62203-hrtb-ice.rs:38:19 + | +LL | let v = Unit2.m( + | ^ type mismatch resolving `for<'r> as T0<'r, (&'r u8,)>>::O == <_ as Ty<'r>>::V` + | +note: expected this to be `<_ as Ty<'_>>::V` + --> $DIR/issue-62203-hrtb-ice.rs:21:14 + | +LL | type O = T::Output; + | ^^^^^^^^^ + = note: expected associated type `<_ as Ty<'_>>::V` + found struct `Unit4` + = help: consider constraining the associated type `<_ as Ty<'_>>::V` to `Unit4` or calling a method that returns `<_ as Ty<'_>>::V` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html +note: required by a bound in `T1::m` + --> $DIR/issue-62203-hrtb-ice.rs:27:51 + | +LL | fn m<'a, B: Ty<'a>, F>(&self, f: F) -> Unit1 + | - required by a bound in this +LL | where +LL | F: for<'r> T0<'r, (>::V,), O = >::V>, + | ^^^^^^^^^^^^^^^^^^^^ required by this bound in `T1::m` + error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0271`.