diff --git a/compiler/rustc_infer/src/infer/type_variable.rs b/compiler/rustc_infer/src/infer/type_variable.rs index 82970f214fa66..6a968005f3eaa 100644 --- a/compiler/rustc_infer/src/infer/type_variable.rs +++ b/compiler/rustc_infer/src/infer/type_variable.rs @@ -259,7 +259,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/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index e8b46e88a4228..d38f4097d56aa 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -213,7 +213,18 @@ fn project_and_unify_type<'cx, 'tcx>( let infcx = selcx.infcx(); // FIXME(associated_const_equality): Handle consts here as well as types. - let obligation_pred_ty = obligation.predicate.term.ty().unwrap(); + // FIXME(compiler-errors): We need to normalize here until we properly handle + // GAT projection types that we can't normalize properly, see note in + // `rustc_trait_selection::traits::project` + let obligation_pred_ty = normalize_with_depth_to( + selcx, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth + 1, + obligation.predicate.term.ty().unwrap(), + &mut obligations, + ); + match infcx.at(&obligation.cause, obligation.param_env).eq(normalized_ty, obligation_pred_ty) { Ok(InferOk { obligations: inferred_obligations, value: () }) => { obligations.extend(inferred_obligations); diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 2e20ea34e10ef..0489c78ea6311 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -555,23 +555,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( @@ -618,26 +603,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")] @@ -659,44 +629,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)) @@ -704,7 +645,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, @@ -735,15 +676,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)) } 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/hrtb/issue-62203-hrtb-ice.rs b/src/test/ui/hrtb/issue-62203-hrtb-ice.rs index 80f099ce3c802..6a13a07f6cf6f 100644 --- a/src/test/ui/hrtb/issue-62203-hrtb-ice.rs +++ b/src/test/ui/hrtb/issue-62203-hrtb-ice.rs @@ -36,7 +36,6 @@ trait Ty<'a> { fn main() { let v = Unit2.m( - //~^ ERROR type mismatch L { //~^ ERROR type mismatch f : |x| { drop(x); Unit4 } diff --git a/src/test/ui/hrtb/issue-62203-hrtb-ice.stderr b/src/test/ui/hrtb/issue-62203-hrtb-ice.stderr index 0ebba37e4ec70..7145a39abfb5a 100644 --- a/src/test/ui/hrtb/issue-62203-hrtb-ice.stderr +++ b/src/test/ui/hrtb/issue-62203-hrtb-ice.stderr @@ -1,40 +1,15 @@ -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 +error[E0271]: type mismatch resolving `for<'r> <[closure@$DIR/issue-62203-hrtb-ice.rs:41:17: 41:39] as FnOnce<((&'r u8,),)>>::Output == Unit3` + --> $DIR/issue-62203-hrtb-ice.rs:39:9 | LL | let v = Unit2.m( | - required by a bound introduced by this call -LL | LL | / L { LL | | LL | | f : |x| { drop(x); Unit4 } LL | | }); | |_________^ expected struct `Unit3`, found struct `Unit4` | -note: required because of the requirements on the impl of `for<'r> T0<'r, (&'r u8,)>` for `L<[closure@$DIR/issue-62203-hrtb-ice.rs:42:17: 42:39]>` +note: required because of the requirements on the impl of `for<'r> T0<'r, (&'r u8,)>` for `L<[closure@$DIR/issue-62203-hrtb-ice.rs:41:17: 41:39]>` --> $DIR/issue-62203-hrtb-ice.rs:17:16 | LL | impl<'a, A, T> T0<'a, A> for L @@ -48,6 +23,6 @@ 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 +error: aborting due to previous error For more information about this error, try `rustc --explain E0271`.