/// Supertrait reference references `Self` an in illegal location
/// (e.g., `trait Foo : Bar<Self>`).
- SupertraitSelf,
+ SupertraitSelf(SmallVec<[Span; 1]>),
/// Method has something illegal.
Method(ast::Name, MethodViolationCode, Span),
pub fn error_msg(&self) -> Cow<'static, str> {
match *self {
ObjectSafetyViolation::SizedSelf(_) => "it requires `Self: Sized`".into(),
- ObjectSafetyViolation::SupertraitSelf => {
- "it cannot use `Self` as a type parameter in the supertraits or `where`-clauses"
- .into()
+ ObjectSafetyViolation::SupertraitSelf(ref spans) => {
+ if spans.iter().any(|sp| *sp != DUMMY_SP) {
+ "it uses `Self` as a type parameter in this".into()
+ } else {
+ "it cannot use `Self` as a type parameter in a supertrait or `where`-clause"
+ .into()
+ }
}
ObjectSafetyViolation::Method(name, MethodViolationCode::StaticMethod(_), _) => {
format!("associated function `{}` has no `self` parameter", name).into()
pub fn solution(&self) -> Option<(String, Option<(String, Span)>)> {
Some(match *self {
- ObjectSafetyViolation::SizedSelf(_) | ObjectSafetyViolation::SupertraitSelf => {
+ ObjectSafetyViolation::SizedSelf(_) | ObjectSafetyViolation::SupertraitSelf(_) => {
return None;
}
ObjectSafetyViolation::Method(name, MethodViolationCode::StaticMethod(sugg), _) => (
// When `span` comes from a separate crate, it'll be `DUMMY_SP`. Treat it as `None` so
// diagnostics use a `note` instead of a `span_label`.
match self {
- ObjectSafetyViolation::SizedSelf(spans) => spans.clone(),
+ ObjectSafetyViolation::SupertraitSelf(spans)
+ | ObjectSafetyViolation::SizedSelf(spans) => spans.clone(),
ObjectSafetyViolation::AssocConst(_, span)
| ObjectSafetyViolation::Method(_, _, span)
if *span != DUMMY_SP =>
) -> Vec<ObjectSafetyViolation> {
debug_assert!(tcx.generics_of(trait_def_id).has_self);
let violations = traits::supertrait_def_ids(tcx, trait_def_id)
- .filter(|&def_id| predicates_reference_self(tcx, def_id, true))
- .map(|_| ObjectSafetyViolation::SupertraitSelf)
+ .map(|def_id| predicates_reference_self(tcx, def_id, true))
+ .filter(|spans| !spans.is_empty())
+ .map(|spans| ObjectSafetyViolation::SupertraitSelf(spans))
.collect();
debug!("astconv_object_safety_violations(trait_def_id={:?}) = {:?}", trait_def_id, violations);
let spans = get_sized_bounds(tcx, trait_def_id);
violations.push(ObjectSafetyViolation::SizedSelf(spans));
}
- if predicates_reference_self(tcx, trait_def_id, false) {
- violations.push(ObjectSafetyViolation::SupertraitSelf);
+ let spans = predicates_reference_self(tcx, trait_def_id, false);
+ if !spans.is_empty() {
+ violations.push(ObjectSafetyViolation::SupertraitSelf(spans));
}
violations.extend(
.unwrap_or_else(SmallVec::new)
}
-fn predicates_reference_self(tcx: TyCtxt<'_>, trait_def_id: DefId, supertraits_only: bool) -> bool {
+fn predicates_reference_self(
+ tcx: TyCtxt<'_>,
+ trait_def_id: DefId,
+ supertraits_only: bool,
+) -> SmallVec<[Span; 1]> {
let trait_ref = ty::Binder::dummy(ty::TraitRef::identity(tcx, trait_def_id));
let predicates = if supertraits_only {
tcx.super_predicates_of(trait_def_id)
predicates
.predicates
.iter()
- .map(|(predicate, _)| predicate.subst_supertrait(tcx, &trait_ref))
- .any(|predicate| {
+ .map(|(predicate, sp)| (predicate.subst_supertrait(tcx, &trait_ref), sp))
+ .filter_map(|(predicate, &sp)| {
match predicate {
ty::Predicate::Trait(ref data, _) => {
// In the case of a trait predicate, we can skip the "self" type.
- data.skip_binder().input_types().skip(1).any(has_self_ty)
+ if data.skip_binder().input_types().skip(1).any(has_self_ty) {
+ Some(sp)
+ } else {
+ None
+ }
}
ty::Predicate::Projection(ref data) => {
// And similarly for projections. This should be redundant with
//
// This is ALT2 in issue #56288, see that for discussion of the
// possible alternatives.
- data.skip_binder()
+ if data
+ .skip_binder()
.projection_ty
.trait_ref(tcx)
.input_types()
.skip(1)
.any(has_self_ty)
+ {
+ Some(sp)
+ } else {
+ None
+ }
}
ty::Predicate::WellFormed(..)
| ty::Predicate::ObjectSafe(..)
| ty::Predicate::RegionOutlives(..)
| ty::Predicate::ClosureKind(..)
| ty::Predicate::Subtype(..)
- | ty::Predicate::ConstEvaluatable(..) => false,
+ | ty::Predicate::ConstEvaluatable(..) => None,
}
})
+ .collect()
}
fn trait_has_sized_self(tcx: TyCtxt<'_>, trait_def_id: DefId) -> bool {
error[E0038]: the trait `Foo` cannot be made into an object
--> $DIR/issue-38604.rs:14:13
|
+LL | trait Foo where u32: Q<Self> {
+ | --- ------- ...because it uses `Self` as a type parameter in this
+ | |
+ | this trait cannot be made into an object...
+...
LL | let _f: Box<dyn Foo> =
| ^^^^^^^^^^^^ the trait `Foo` cannot be made into an object
- |
- = note: the trait cannot be made into an object because it cannot use `Self` as a type parameter in the supertraits or `where`-clauses
error[E0038]: the trait `Foo` cannot be made into an object
--> $DIR/issue-38604.rs:15:9
|
+LL | trait Foo where u32: Q<Self> {
+ | --- ------- ...because it uses `Self` as a type parameter in this
+ | |
+ | this trait cannot be made into an object...
+...
LL | Box::new(());
| ^^^^^^^^^^^^ the trait `Foo` cannot be made into an object
|
- = note: the trait cannot be made into an object because it cannot use `Self` as a type parameter in the supertraits or `where`-clauses
= note: required because of the requirements on the impl of `std::ops::CoerceUnsized<std::boxed::Box<dyn Foo>>` for `std::boxed::Box<()>`
= note: required by cast to type `std::boxed::Box<dyn Foo>`