Auto merge of #115538 - lcnr:fn-def-wf, r=compiler-errors
check `FnDef` return type for WF better version of #106807, fixes #84533 (mostly). It's not perfect given that we still ignore WF requirements involving bound regions but I wasn't able to quickly write an example, so even if theoretically exploitable, it should be far harder to trigger. This is strictly more restrictive than checking the return type for WF as part of the builtin `FnDef: FnOnce` impl (#106807) and moving to this approach in the future will not break any code. ~~It also agrees with my theoretical view of how this should behave~~ r? types
This commit is contained in:
commit
4c6c629866
8 changed files with 153 additions and 45 deletions
|
@ -647,6 +647,8 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {
|
|||
fn visit_ty(&mut self, t: <TyCtxt<'tcx> as ty::Interner>::Ty) -> Self::Result {
|
||||
debug!("wf bounds for t={:?} t.kind={:#?}", t, t.kind());
|
||||
|
||||
let tcx = self.tcx();
|
||||
|
||||
match *t.kind() {
|
||||
ty::Bool
|
||||
| ty::Char
|
||||
|
@ -707,6 +709,16 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {
|
|||
}
|
||||
|
||||
ty::FnDef(did, args) => {
|
||||
// HACK: Check the return type of function definitions for
|
||||
// well-formedness to mostly fix #84533. This is still not
|
||||
// perfect and there may be ways to abuse the fact that we
|
||||
// ignore requirements with escaping bound vars. That's a
|
||||
// more general issue however.
|
||||
//
|
||||
// FIXME(eddyb) add the type to `walker` instead of recursing.
|
||||
let fn_sig = tcx.fn_sig(did).instantiate(tcx, args);
|
||||
fn_sig.output().skip_binder().visit_with(self);
|
||||
|
||||
let obligations = self.nominal_obligations(did, args);
|
||||
self.out.extend(obligations);
|
||||
}
|
||||
|
@ -716,7 +728,7 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {
|
|||
if !r.has_escaping_bound_vars() && !rty.has_escaping_bound_vars() {
|
||||
let cause = self.cause(traits::ReferenceOutlivesReferent(t));
|
||||
self.out.push(traits::Obligation::with_depth(
|
||||
self.tcx(),
|
||||
tcx,
|
||||
cause,
|
||||
self.recursion_depth,
|
||||
self.param_env,
|
||||
|
@ -805,12 +817,12 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {
|
|||
// obligations that don't refer to Self and
|
||||
// checking those
|
||||
|
||||
let defer_to_coercion = self.tcx().features().object_safe_for_dispatch;
|
||||
let defer_to_coercion = tcx.features().object_safe_for_dispatch;
|
||||
|
||||
if !defer_to_coercion {
|
||||
if let Some(principal) = data.principal_def_id() {
|
||||
self.out.push(traits::Obligation::with_depth(
|
||||
self.tcx(),
|
||||
tcx,
|
||||
self.cause(traits::WellFormed(None)),
|
||||
self.recursion_depth,
|
||||
self.param_env,
|
||||
|
@ -835,7 +847,7 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {
|
|||
ty::Infer(_) => {
|
||||
let cause = self.cause(traits::WellFormed(None));
|
||||
self.out.push(traits::Obligation::with_depth(
|
||||
self.tcx(),
|
||||
tcx,
|
||||
cause,
|
||||
self.recursion_depth,
|
||||
self.param_env,
|
||||
|
@ -850,6 +862,8 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {
|
|||
}
|
||||
|
||||
fn visit_const(&mut self, c: <TyCtxt<'tcx> as ty::Interner>::Const) -> Self::Result {
|
||||
let tcx = self.tcx();
|
||||
|
||||
match c.kind() {
|
||||
ty::ConstKind::Unevaluated(uv) => {
|
||||
if !c.has_escaping_bound_vars() {
|
||||
|
@ -861,7 +875,7 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {
|
|||
));
|
||||
let cause = self.cause(traits::WellFormed(None));
|
||||
self.out.push(traits::Obligation::with_depth(
|
||||
self.tcx(),
|
||||
tcx,
|
||||
cause,
|
||||
self.recursion_depth,
|
||||
self.param_env,
|
||||
|
@ -873,7 +887,7 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {
|
|||
let cause = self.cause(traits::WellFormed(None));
|
||||
|
||||
self.out.push(traits::Obligation::with_depth(
|
||||
self.tcx(),
|
||||
tcx,
|
||||
cause,
|
||||
self.recursion_depth,
|
||||
self.param_env,
|
||||
|
@ -895,7 +909,7 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {
|
|||
));
|
||||
let cause = self.cause(traits::WellFormed(None));
|
||||
self.out.push(traits::Obligation::with_depth(
|
||||
self.tcx(),
|
||||
tcx,
|
||||
cause,
|
||||
self.recursion_depth,
|
||||
self.param_env,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue