Closed
Description
The lint is triggered by the following code (from #108345, cc @EqualMa) :
use std::borrow::Cow;
pub trait Trait {
fn method(self) -> Option<Cow<'static, str>>
where
Self: Sized;
}
impl<'a> Trait for Cow<'a, str> {
fn method(self) -> Option<Cow<'static, str>> {
None
}
}
In the environment <'a> where Cow<'a, str>: Sized
, the type Option<Cow<'static, str>>
surprisingly requires 'a == 'static
for well-formedness (see #108345 (comment)), but this constraint is not used in implied bounds, so I believe it can't be exploited for unsoundness.
The lint was upgraded to deny-by-default in the current beta (1.68.0-beta.5 2023-02-15 003b6f2). So this counts as regression?
cc @compiler-errors.
@rustbot label C-bug T-types T-compiler regression-from-stable-to-beta
Activity
compiler-errors commentedon Feb 27, 2023
🤦
I think this is due to us preferring param-env candidates for
Sized
.compiler-errors commentedon Feb 27, 2023
So the issue here is that
WF(Option<Cow<'static, T>>)
requiresCow<'static, T>: Sized
.We try to prove that in the hybrid param-env of the impl's WC + trait method's WC, being
Cow<'a, T>: Sized
after substitutingSelf
.Due to some frustrating precedence rules around candidate assembly in the trait solver, we try to match
Cow<'static, T>: Sized
against the param-env candidateCow<'a, T>: Sized
and get'a == 'static
. We also assemble a built-in sized bound, but always prefer the param-env candidate over that.That requires us to prove
'a: 'static
, which is not known to be true in the hybrid param-env, triggering the lint.compiler-errors commentedon Feb 27, 2023
I wonder if we could get away with not checking
WF(return-type)
, but just the implied lifetime bounds or something 🤔IMPLIED_BOUNDS_ENTAILMENT
lint #105572apiraino commentedon Mar 1, 2023
WG-prioritization assigning priority (Zulip discussion).
@rustbot label -I-prioritize +P-medium
jackh726 commentedon Mar 19, 2023
Been thinking about this a little bit. One thought I had was to check that the impl method is WF given only the trait method, but I think that would break this example:
This is annoying difficult, because it's not straightforward to get "just the implied lifetime bounds" of a type. I'm playing around with using
wf::obligations()
and filtering outlives bounds, but that can generate moreWellFormed
predicates (which, I thought we had somewhere a function that recurses though those). We'll see if this works...14 remaining items