diff options
Diffstat (limited to 'compiler/rustc_middle/src/traits/mod.rs')
| -rw-r--r-- | compiler/rustc_middle/src/traits/mod.rs | 94 |
1 files changed, 71 insertions, 23 deletions
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 1dd6d590d90..4deb7225dcb 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -13,6 +13,7 @@ use crate::mir::interpret::ErrorHandled; use crate::ty::subst::SubstsRef; use crate::ty::{self, AdtKind, Ty, TyCtxt}; +use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_span::symbol::Symbol; @@ -339,10 +340,24 @@ impl ObligationCauseCode<'_> { #[cfg(target_arch = "x86_64")] static_assert_size!(ObligationCauseCode<'_>, 32); +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +pub enum StatementAsExpression { + CorrectType, + NeedsBoxing, +} + +impl<'tcx> ty::Lift<'tcx> for StatementAsExpression { + type Lifted = StatementAsExpression; + fn lift_to_tcx(self, _tcx: TyCtxt<'tcx>) -> Option<StatementAsExpression> { + Some(self) + } +} + #[derive(Clone, Debug, PartialEq, Eq, Hash, Lift)] pub struct MatchExpressionArmCause<'tcx> { pub arm_span: Span, - pub semi_span: Option<Span>, + pub scrut_span: Span, + pub semi_span: Option<(Span, StatementAsExpression)>, pub source: hir::MatchSource, pub prior_arms: Vec<Span>, pub last_ty: Ty<'tcx>, @@ -355,7 +370,7 @@ pub struct IfExpressionCause { pub then: Span, pub else_sp: Span, pub outer: Option<Span>, - pub semicolon: Option<Span>, + pub semicolon: Option<(Span, StatementAsExpression)>, pub opt_suggest_box_span: Option<Span>, } @@ -646,13 +661,13 @@ impl ObjectSafetyViolation { ObjectSafetyViolation::SizedSelf(_) => "it requires `Self: Sized`".into(), ObjectSafetyViolation::SupertraitSelf(ref spans) => { if spans.iter().any(|sp| *sp != DUMMY_SP) { - "it uses `Self` as a type parameter in this".into() + "it uses `Self` as a type parameter".into() } else { "it cannot use `Self` as a type parameter in a supertrait or `where`-clause" .into() } } - ObjectSafetyViolation::Method(name, MethodViolationCode::StaticMethod(_), _) => { + ObjectSafetyViolation::Method(name, MethodViolationCode::StaticMethod(_, _, _), _) => { format!("associated function `{}` has no `self` parameter", name).into() } ObjectSafetyViolation::Method( @@ -686,32 +701,65 @@ impl ObjectSafetyViolation { } } - pub fn solution(&self) -> Option<(String, Option<(String, Span)>)> { - Some(match *self { - ObjectSafetyViolation::SizedSelf(_) | ObjectSafetyViolation::SupertraitSelf(_) => { - return None; + pub fn solution(&self, err: &mut DiagnosticBuilder<'_>) { + match *self { + ObjectSafetyViolation::SizedSelf(_) | ObjectSafetyViolation::SupertraitSelf(_) => {} + ObjectSafetyViolation::Method( + name, + MethodViolationCode::StaticMethod(sugg, self_span, has_args), + _, + ) => { + err.span_suggestion( + self_span, + &format!( + "consider turning `{}` into a method by giving it a `&self` argument", + name + ), + format!("&self{}", if has_args { ", " } else { "" }), + Applicability::MaybeIncorrect, + ); + match sugg { + Some((sugg, span)) => { + err.span_suggestion( + span, + &format!( + "alternatively, consider constraining `{}` so it does not apply to \ + trait objects", + name + ), + sugg.to_string(), + Applicability::MaybeIncorrect, + ); + } + None => { + err.help(&format!( + "consider turning `{}` into a method by giving it a `&self` \ + argument or constraining it so it does not apply to trait objects", + name + )); + } + } } - ObjectSafetyViolation::Method(name, MethodViolationCode::StaticMethod(sugg), _) => ( - format!( - "consider turning `{}` into a method by giving it a `&self` argument or \ - constraining it so it does not apply to trait objects", - name - ), - sugg.map(|(sugg, sp)| (sugg.to_string(), sp)), - ), ObjectSafetyViolation::Method( name, MethodViolationCode::UndispatchableReceiver, span, - ) => ( - format!("consider changing method `{}`'s `self` parameter to be `&self`", name), - Some(("&Self".to_string(), span)), - ), + ) => { + err.span_suggestion( + span, + &format!( + "consider changing method `{}`'s `self` parameter to be `&self`", + name + ), + "&Self".to_string(), + Applicability::MachineApplicable, + ); + } ObjectSafetyViolation::AssocConst(name, _) | ObjectSafetyViolation::Method(name, ..) => { - (format!("consider moving `{}` to another trait", name), None) + err.help(&format!("consider moving `{}` to another trait", name)); } - }) + } } pub fn spans(&self) -> SmallVec<[Span; 1]> { @@ -735,7 +783,7 @@ impl ObjectSafetyViolation { #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)] pub enum MethodViolationCode { /// e.g., `fn foo()` - StaticMethod(Option<(&'static str, Span)>), + StaticMethod(Option<(&'static str, Span)>, Span, bool /* has args */), /// e.g., `fn foo(&self, x: Self)` ReferencesSelfInput(usize), |
