Check WhereClauseReferencesSelf after all other object safety checks

This commit is contained in:
Michael Goulet 2022-10-07 02:29:19 +00:00
parent 0ca356586f
commit 414319468b
3 changed files with 61 additions and 13 deletions

View File

@ -447,19 +447,6 @@ fn virtual_call_violation_for_method<'tcx>(
return Some(MethodViolationCode::Generic);
}
if tcx
.predicates_of(method.def_id)
.predicates
.iter()
// A trait object can't claim to live more than the concrete type,
// so outlives predicates will always hold.
.cloned()
.filter(|(p, _)| p.to_opt_type_outlives().is_none())
.any(|pred| contains_illegal_self_type_reference(tcx, trait_def_id, pred))
{
return Some(MethodViolationCode::WhereClauseReferencesSelf);
}
let receiver_ty = tcx.liberate_late_bound_regions(method.def_id, sig.input(0));
// Until `unsized_locals` is fully implemented, `self: Self` can't be dispatched on.
@ -538,6 +525,21 @@ fn virtual_call_violation_for_method<'tcx>(
}
}
// NOTE: This check happens last, because it results in a lint, and not a
// hard error.
if tcx
.predicates_of(method.def_id)
.predicates
.iter()
// A trait object can't claim to live more than the concrete type,
// so outlives predicates will always hold.
.cloned()
.filter(|(p, _)| p.to_opt_type_outlives().is_none())
.any(|pred| contains_illegal_self_type_reference(tcx, trait_def_id, pred))
{
return Some(MethodViolationCode::WhereClauseReferencesSelf);
}
None
}

View File

@ -0,0 +1,26 @@
// compile-flags: --crate-type=lib
// This test checks that the `where_clauses_object_safety` lint does not cause
// other object safety *hard errors* to be suppressed, because we currently
// only emit one object safety error per trait...
use std::future::Future;
use std::pin::Pin;
pub trait Fetcher: Send + Sync {
fn get<'a>(self: &'a Box<Self>) -> Pin<Box<dyn Future<Output = Vec<u8>> + 'a>>
where
Self: Sync,
{
todo!()
}
}
fn fetcher() -> Box<dyn Fetcher> {
//~^ ERROR the trait `Fetcher` cannot be made into an object
todo!()
}
pub fn foo() {
let fetcher = fetcher();
let _ = fetcher.get();
}

View File

@ -0,0 +1,20 @@
error[E0038]: the trait `Fetcher` cannot be made into an object
--> $DIR/issue-102762.rs:18:21
|
LL | fn get<'a>(self: &'a Box<Self>) -> Pin<Box<dyn Future<Output = Vec<u8>> + 'a>>
| ------------- help: consider changing method `get`'s `self` parameter to be `&self`: `&Self`
...
LL | fn fetcher() -> Box<dyn Fetcher> {
| ^^^^^^^^^^^ `Fetcher` cannot be made into an object
|
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/issue-102762.rs:10:22
|
LL | pub trait Fetcher: Send + Sync {
| ------- this trait cannot be made into an object...
LL | fn get<'a>(self: &'a Box<Self>) -> Pin<Box<dyn Future<Output = Vec<u8>> + 'a>>
| ^^^^^^^^^^^^^ ...because method `get`'s `self` parameter cannot be dispatched on
error: aborting due to previous error
For more information about this error, try `rustc --explain E0038`.