review comments
This commit is contained in:
parent
9fb446d472
commit
0f530ecb68
3 changed files with 81 additions and 77 deletions
|
@ -16,9 +16,9 @@ use crate::ty::AdtKind;
|
||||||
use crate::ty::query::Providers;
|
use crate::ty::query::Providers;
|
||||||
use crate::util::nodemap::{NodeMap, FxHashSet};
|
use crate::util::nodemap::{NodeMap, FxHashSet};
|
||||||
|
|
||||||
use errors::{Applicability, DiagnosticBuilder, FatalError};
|
use errors::FatalError;
|
||||||
use syntax_pos::{Span, DUMMY_SP, MultiSpan};
|
use syntax_pos::{Span, DUMMY_SP, MultiSpan};
|
||||||
use syntax::source_map::{Spanned, SourceMap};
|
use syntax::source_map::Spanned;
|
||||||
use syntax::ast::{self, CrateSugar, Ident, Name, NodeId, AsmDialect};
|
use syntax::ast::{self, CrateSugar, Ident, Name, NodeId, AsmDialect};
|
||||||
use syntax::ast::{Attribute, Label, LitKind, StrStyle, FloatTy, IntTy, UintTy};
|
use syntax::ast::{Attribute, Label, LitKind, StrStyle, FloatTy, IntTy, UintTy};
|
||||||
pub use syntax::ast::{Mutability, Constness, Unsafety, Movability, CaptureBy};
|
pub use syntax::ast::{Mutability, Constness, Unsafety, Movability, CaptureBy};
|
||||||
|
@ -644,79 +644,6 @@ impl Generics {
|
||||||
self.params.iter().map(|p| p.span).collect::<Vec<Span>>().into()
|
self.params.iter().map(|p| p.span).collect::<Vec<Span>>().into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Suggest restricting a type param with a new bound.
|
|
||||||
pub fn suggest_constraining_type_param(
|
|
||||||
&self,
|
|
||||||
err: &mut DiagnosticBuilder<'_>,
|
|
||||||
param_name: &str,
|
|
||||||
constraint: &str,
|
|
||||||
source_map: &SourceMap,
|
|
||||||
span: Span,
|
|
||||||
) -> bool {
|
|
||||||
let restrict_msg = "consider further restricting this bound";
|
|
||||||
if let Some(param) = self.params.iter().filter(|p| {
|
|
||||||
p.name.ident().as_str() == param_name
|
|
||||||
}).next() {
|
|
||||||
if param_name.starts_with("impl ") {
|
|
||||||
// `impl Trait` in argument:
|
|
||||||
// `fn foo(x: impl Trait) {}` → `fn foo(t: impl Trait + Trait2) {}`
|
|
||||||
err.span_suggestion(
|
|
||||||
param.span,
|
|
||||||
restrict_msg,
|
|
||||||
// `impl CurrentTrait + MissingTrait`
|
|
||||||
format!("{} + {}", param_name, constraint),
|
|
||||||
Applicability::MachineApplicable,
|
|
||||||
);
|
|
||||||
} else if self.where_clause.predicates.is_empty() &&
|
|
||||||
param.bounds.is_empty()
|
|
||||||
{
|
|
||||||
// If there are no bounds whatsoever, suggest adding a constraint
|
|
||||||
// to the type parameter:
|
|
||||||
// `fn foo<T>(t: T) {}` → `fn foo<T: Trait>(t: T) {}`
|
|
||||||
err.span_suggestion(
|
|
||||||
param.span,
|
|
||||||
"consider restricting this bound",
|
|
||||||
format!("{}: {}", param_name, constraint),
|
|
||||||
Applicability::MachineApplicable,
|
|
||||||
);
|
|
||||||
} else if !self.where_clause.predicates.is_empty() {
|
|
||||||
// There is a `where` clause, so suggest expanding it:
|
|
||||||
// `fn foo<T>(t: T) where T: Debug {}` →
|
|
||||||
// `fn foo<T>(t: T) where T: Debug, T: Trait {}`
|
|
||||||
err.span_suggestion(
|
|
||||||
self.where_clause.span().unwrap().shrink_to_hi(),
|
|
||||||
&format!("consider further restricting type parameter `{}`", param_name),
|
|
||||||
format!(", {}: {}", param_name, constraint),
|
|
||||||
Applicability::MachineApplicable,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
// If there is no `where` clause lean towards constraining to the
|
|
||||||
// type parameter:
|
|
||||||
// `fn foo<X: Bar, T>(t: T, x: X) {}` → `fn foo<T: Trait>(t: T) {}`
|
|
||||||
// `fn foo<T: Bar>(t: T) {}` → `fn foo<T: Bar + Trait>(t: T) {}`
|
|
||||||
let sp = param.span.with_hi(span.hi());
|
|
||||||
let span = source_map.span_through_char(sp, ':');
|
|
||||||
if sp != param.span && sp != span {
|
|
||||||
// Only suggest if we have high certainty that the span
|
|
||||||
// covers the colon in `foo<T: Trait>`.
|
|
||||||
err.span_suggestion(
|
|
||||||
span,
|
|
||||||
restrict_msg,
|
|
||||||
format!("{}: {} + ", param_name, constraint),
|
|
||||||
Applicability::MachineApplicable,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
err.span_label(
|
|
||||||
param.span,
|
|
||||||
&format!("consider adding a `where {}: {}` bound", param_name, constraint),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Synthetic type parameters are converted to another form during lowering; this allows
|
/// Synthetic type parameters are converted to another form during lowering; this allows
|
||||||
|
|
|
@ -39,6 +39,7 @@ use syntax::ast;
|
||||||
use syntax::symbol::{sym, kw};
|
use syntax::symbol::{sym, kw};
|
||||||
use syntax_pos::{DUMMY_SP, Span, ExpnKind, MultiSpan};
|
use syntax_pos::{DUMMY_SP, Span, ExpnKind, MultiSpan};
|
||||||
use rustc::hir::def_id::LOCAL_CRATE;
|
use rustc::hir::def_id::LOCAL_CRATE;
|
||||||
|
use syntax_pos::source_map::SourceMap;
|
||||||
|
|
||||||
use rustc_error_codes::*;
|
use rustc_error_codes::*;
|
||||||
|
|
||||||
|
@ -1189,7 +1190,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||||
// Missing generic type parameter bound.
|
// Missing generic type parameter bound.
|
||||||
let param_name = self_ty.to_string();
|
let param_name = self_ty.to_string();
|
||||||
let constraint = trait_ref.to_string();
|
let constraint = trait_ref.to_string();
|
||||||
if generics.suggest_constraining_type_param(
|
if suggest_constraining_type_param(
|
||||||
|
generics,
|
||||||
&mut err,
|
&mut err,
|
||||||
¶m_name,
|
¶m_name,
|
||||||
&constraint,
|
&constraint,
|
||||||
|
@ -2497,3 +2499,76 @@ impl ArgKind {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Suggest restricting a type param with a new bound.
|
||||||
|
pub fn suggest_constraining_type_param(
|
||||||
|
generics: &hir::Generics,
|
||||||
|
err: &mut DiagnosticBuilder<'_>,
|
||||||
|
param_name: &str,
|
||||||
|
constraint: &str,
|
||||||
|
source_map: &SourceMap,
|
||||||
|
span: Span,
|
||||||
|
) -> bool {
|
||||||
|
let restrict_msg = "consider further restricting this bound";
|
||||||
|
if let Some(param) = generics.params.iter().filter(|p| {
|
||||||
|
p.name.ident().as_str() == param_name
|
||||||
|
}).next() {
|
||||||
|
if param_name.starts_with("impl ") {
|
||||||
|
// `impl Trait` in argument:
|
||||||
|
// `fn foo(x: impl Trait) {}` → `fn foo(t: impl Trait + Trait2) {}`
|
||||||
|
err.span_suggestion(
|
||||||
|
param.span,
|
||||||
|
restrict_msg,
|
||||||
|
// `impl CurrentTrait + MissingTrait`
|
||||||
|
format!("{} + {}", param_name, constraint),
|
||||||
|
Applicability::MachineApplicable,
|
||||||
|
);
|
||||||
|
} else if generics.where_clause.predicates.is_empty() &&
|
||||||
|
param.bounds.is_empty()
|
||||||
|
{
|
||||||
|
// If there are no bounds whatsoever, suggest adding a constraint
|
||||||
|
// to the type parameter:
|
||||||
|
// `fn foo<T>(t: T) {}` → `fn foo<T: Trait>(t: T) {}`
|
||||||
|
err.span_suggestion(
|
||||||
|
param.span,
|
||||||
|
"consider restricting this bound",
|
||||||
|
format!("{}: {}", param_name, constraint),
|
||||||
|
Applicability::MachineApplicable,
|
||||||
|
);
|
||||||
|
} else if !generics.where_clause.predicates.is_empty() {
|
||||||
|
// There is a `where` clause, so suggest expanding it:
|
||||||
|
// `fn foo<T>(t: T) where T: Debug {}` →
|
||||||
|
// `fn foo<T>(t: T) where T: Debug, T: Trait {}`
|
||||||
|
err.span_suggestion(
|
||||||
|
generics.where_clause.span().unwrap().shrink_to_hi(),
|
||||||
|
&format!("consider further restricting type parameter `{}`", param_name),
|
||||||
|
format!(", {}: {}", param_name, constraint),
|
||||||
|
Applicability::MachineApplicable,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// If there is no `where` clause lean towards constraining to the
|
||||||
|
// type parameter:
|
||||||
|
// `fn foo<X: Bar, T>(t: T, x: X) {}` → `fn foo<T: Trait>(t: T) {}`
|
||||||
|
// `fn foo<T: Bar>(t: T) {}` → `fn foo<T: Bar + Trait>(t: T) {}`
|
||||||
|
let sp = param.span.with_hi(span.hi());
|
||||||
|
let span = source_map.span_through_char(sp, ':');
|
||||||
|
if sp != param.span && sp != span {
|
||||||
|
// Only suggest if we have high certainty that the span
|
||||||
|
// covers the colon in `foo<T: Trait>`.
|
||||||
|
err.span_suggestion(
|
||||||
|
span,
|
||||||
|
restrict_msg,
|
||||||
|
format!("{}: {} + ", param_name, constraint),
|
||||||
|
Applicability::MachineApplicable,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
err.span_label(
|
||||||
|
param.span,
|
||||||
|
&format!("consider adding a `where {}: {}` bound", param_name, constraint),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ use rustc::mir::{
|
||||||
PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, TerminatorKind, VarBindingForm,
|
PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, TerminatorKind, VarBindingForm,
|
||||||
};
|
};
|
||||||
use rustc::ty::{self, Ty};
|
use rustc::ty::{self, Ty};
|
||||||
|
use rustc::traits::error_reporting::suggest_constraining_type_param;
|
||||||
use rustc_data_structures::fx::FxHashSet;
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
use rustc_index::vec::Idx;
|
use rustc_index::vec::Idx;
|
||||||
use rustc_errors::{Applicability, DiagnosticBuilder};
|
use rustc_errors::{Applicability, DiagnosticBuilder};
|
||||||
|
@ -233,7 +234,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
let generics = tcx.generics_of(self.mir_def_id);
|
let generics = tcx.generics_of(self.mir_def_id);
|
||||||
let param = generics.type_param(¶m_ty, tcx);
|
let param = generics.type_param(¶m_ty, tcx);
|
||||||
let generics = tcx.hir().get_generics(self.mir_def_id).unwrap();
|
let generics = tcx.hir().get_generics(self.mir_def_id).unwrap();
|
||||||
generics.suggest_constraining_type_param(
|
suggest_constraining_type_param(
|
||||||
|
generics,
|
||||||
&mut err,
|
&mut err,
|
||||||
¶m.name.as_str(),
|
¶m.name.as_str(),
|
||||||
"Copy",
|
"Copy",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue