parent
9832374f6e
commit
ae0e3d0511
57 changed files with 720 additions and 442 deletions
|
@ -13,7 +13,7 @@ use super::elaborate_predicates;
|
|||
use crate::infer::TyCtxtInferExt;
|
||||
use crate::traits::query::evaluate_obligation::InferCtxtExt;
|
||||
use crate::traits::{self, Obligation, ObligationCause};
|
||||
use rustc_errors::{Applicability, FatalError};
|
||||
use rustc_errors::FatalError;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_middle::ty::subst::{GenericArg, InternalSubsts, Subst};
|
||||
|
@ -21,7 +21,7 @@ use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeVisitor, WithConstnes
|
|||
use rustc_middle::ty::{Predicate, ToPredicate};
|
||||
use rustc_session::lint::builtin::WHERE_CLAUSES_OBJECT_SAFETY;
|
||||
use rustc_span::symbol::Symbol;
|
||||
use rustc_span::Span;
|
||||
use rustc_span::{MultiSpan, Span};
|
||||
use smallvec::SmallVec;
|
||||
|
||||
use std::array;
|
||||
|
@ -112,33 +112,35 @@ fn object_safety_violations_for_trait(
|
|||
tcx.def_path_str(trait_def_id)
|
||||
));
|
||||
let node = tcx.hir().get_if_local(trait_def_id);
|
||||
let msg = if let Some(hir::Node::Item(item)) = node {
|
||||
err.span_label(
|
||||
let mut spans = MultiSpan::from_span(*span);
|
||||
if let Some(hir::Node::Item(item)) = node {
|
||||
spans.push_span_label(
|
||||
item.ident.span,
|
||||
"this trait cannot be made into an object...",
|
||||
"this trait cannot be made into an object...".into(),
|
||||
);
|
||||
spans.push_span_label(
|
||||
*span,
|
||||
format!("...because {}", violation.error_msg()),
|
||||
);
|
||||
format!("...because {}", violation.error_msg())
|
||||
} else {
|
||||
format!(
|
||||
"the trait cannot be made into an object because {}",
|
||||
violation.error_msg()
|
||||
)
|
||||
spans.push_span_label(
|
||||
*span,
|
||||
format!(
|
||||
"the trait cannot be made into an object because {}",
|
||||
violation.error_msg()
|
||||
),
|
||||
);
|
||||
};
|
||||
err.span_label(*span, &msg);
|
||||
match (node, violation.solution()) {
|
||||
(Some(_), Some((note, None))) => {
|
||||
err.help(¬e);
|
||||
}
|
||||
(Some(_), Some((note, Some((sugg, span))))) => {
|
||||
err.span_suggestion(
|
||||
span,
|
||||
¬e,
|
||||
sugg,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
// Only provide the help if its a local trait, otherwise it's not actionable.
|
||||
_ => {}
|
||||
err.span_note(
|
||||
spans,
|
||||
"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>",
|
||||
);
|
||||
if node.is_some() {
|
||||
// Only provide the help if its a local trait, otherwise it's not
|
||||
violation.solution(&mut err);
|
||||
}
|
||||
err.emit();
|
||||
},
|
||||
|
@ -385,6 +387,8 @@ fn virtual_call_violation_for_method<'tcx>(
|
|||
trait_def_id: DefId,
|
||||
method: &ty::AssocItem,
|
||||
) -> Option<MethodViolationCode> {
|
||||
let sig = tcx.fn_sig(method.def_id);
|
||||
|
||||
// The method's first parameter must be named `self`
|
||||
if !method.fn_has_self_parameter {
|
||||
// We'll attempt to provide a structured suggestion for `Self: Sized`.
|
||||
|
@ -395,11 +399,21 @@ fn virtual_call_violation_for_method<'tcx>(
|
|||
[.., pred] => (", Self: Sized", pred.span().shrink_to_hi()),
|
||||
},
|
||||
);
|
||||
return Some(MethodViolationCode::StaticMethod(sugg));
|
||||
// Get the span pointing at where the `self` receiver should be.
|
||||
let sm = tcx.sess.source_map();
|
||||
let self_span = method.ident.span.to(tcx
|
||||
.hir()
|
||||
.span_if_local(method.def_id)
|
||||
.unwrap_or_else(|| sm.next_point(method.ident.span))
|
||||
.shrink_to_hi());
|
||||
let self_span = sm.span_through_char(self_span, '(').shrink_to_hi();
|
||||
return Some(MethodViolationCode::StaticMethod(
|
||||
sugg,
|
||||
self_span,
|
||||
!sig.inputs().skip_binder().is_empty(),
|
||||
));
|
||||
}
|
||||
|
||||
let sig = tcx.fn_sig(method.def_id);
|
||||
|
||||
for (i, input_ty) in sig.skip_binder().inputs()[1..].iter().enumerate() {
|
||||
if contains_illegal_self_type_reference(tcx, trait_def_id, input_ty) {
|
||||
return Some(MethodViolationCode::ReferencesSelfInput(i));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue