mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-29 16:13:40 +00:00
Check WhereClauseReferencesSelf after all other object safety checks
This commit is contained in:
parent
0ca356586f
commit
414319468b
@ -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
|
||||
}
|
||||
|
||||
|
26
src/test/ui/object-safety/issue-102762.rs
Normal file
26
src/test/ui/object-safety/issue-102762.rs
Normal 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();
|
||||
}
|
20
src/test/ui/object-safety/issue-102762.stderr
Normal file
20
src/test/ui/object-safety/issue-102762.stderr
Normal 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`.
|
Loading…
Reference in New Issue
Block a user