From 6069317d40c1df4673e039bc66929c9aad36a8a5 Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 13 Jan 2023 13:39:48 +0100 Subject: [PATCH] builtin Fn impl, require return type wf --- .../src/traits/select/confirmation.rs | 18 ++++++++++++++++++ .../lifetimes/lifetime-errors/issue_74400.rs | 1 + .../lifetime-errors/issue_74400.stderr | 13 ++++++++++++- .../issue-53398-cyclic-types.stderr | 2 +- 4 files changed, 32 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index a41d10f104358..ab09995154dd1 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -619,8 +619,26 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .map_bound(|(trait_ref, _)| trait_ref); let mut nested = self.confirm_poly_trait_refs(obligation, trait_ref)?; + let cause = obligation.derived_cause(BuiltinDerivedObligation); + // Require the output to be well formed as it is otherwise possible to have an + // impl with an associated type which isn't well formed, which is unsound. + // + // FIXME: using `no_bound_vars` as we cannot deal with implied bounds for late-bound + // lifetimes right now. + // + // FIXME: move this to the wf requirements of function definitions themselves instead. + if let Some(return_ty) = sig.output().no_bound_vars() { + nested.push(Obligation::new( + tcx, + cause.clone(), + obligation.param_env, + ty::Binder::dummy(ty::PredicateKind::WellFormed(return_ty.into())), + )); + } + + if obligation.is_const() && !is_const { // function is a trait method if let ty::FnDef(def_id, substs) = self_ty.kind() && let Some(trait_id) = tcx.trait_of_item(*def_id) { diff --git a/tests/ui/lifetimes/lifetime-errors/issue_74400.rs b/tests/ui/lifetimes/lifetime-errors/issue_74400.rs index ddb8bacce8f90..69f868bdfb9c5 100644 --- a/tests/ui/lifetimes/lifetime-errors/issue_74400.rs +++ b/tests/ui/lifetimes/lifetime-errors/issue_74400.rs @@ -11,6 +11,7 @@ fn f(data: &[T], key: impl Fn(&T) -> S) { fn g(data: &[T]) { f(data, identity) //~^ ERROR the parameter type + //~| ERROR the parameter type //~| ERROR mismatched types //~| ERROR implementation of `FnOnce` is not general } diff --git a/tests/ui/lifetimes/lifetime-errors/issue_74400.stderr b/tests/ui/lifetimes/lifetime-errors/issue_74400.stderr index 7049f28e2f6eb..7d214ee8dd48b 100644 --- a/tests/ui/lifetimes/lifetime-errors/issue_74400.stderr +++ b/tests/ui/lifetimes/lifetime-errors/issue_74400.stderr @@ -9,6 +9,17 @@ help: consider adding an explicit lifetime bound... LL | fn g(data: &[T]) { | +++++++++ +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/issue_74400.rs:12:5 + | +LL | f(data, identity) + | ^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn g(data: &[T]) { + | +++++++++ + error[E0308]: mismatched types --> $DIR/issue_74400.rs:12:5 | @@ -32,7 +43,7 @@ LL | f(data, identity) = note: `fn(&'2 T) -> &'2 T {identity::<&'2 T>}` must implement `FnOnce<(&'1 T,)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 T,)>`, for some specific lifetime `'2` -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors Some errors have detailed explanations: E0308, E0310. For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.stderr b/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.stderr index 0a34e8486a551..c69f766765afc 100644 --- a/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.stderr +++ b/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.stderr @@ -1,4 +1,4 @@ -error[E0275]: overflow evaluating the requirement `Foo: Sized` +error[E0275]: overflow evaluating the requirement `Foo well-formed` --> $DIR/issue-53398-cyclic-types.rs:5:13 | LL | fn foo() -> Foo {