impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnsafeCode {
fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) {
- if let hir::ExprBlock(ref blk) = e.node {
+ if let hir::ExprBlock(ref blk, _) = e.node {
// Don't warn about generated blocks, that'll just pollute the output.
if blk.rules == hir::UnsafeBlock(hir::UserProvided) {
self.report_unsafe(cx, blk.span, "usage of an `unsafe` block");
if !ty.moves_by_default(cx.tcx, param_env, item.span) {
return;
}
- if param_env.can_type_implement_copy(cx.tcx, ty, item.span).is_ok() {
+ if param_env.can_type_implement_copy(cx.tcx, ty).is_ok() {
cx.span_lint(MISSING_COPY_IMPLEMENTATIONS,
item.span,
"type could implement `Copy`; consider adding `impl \
impl UnreachablePub {
fn perform_lint(&self, cx: &LateContext, what: &str, id: ast::NodeId,
- vis: &hir::Visibility, span: Span, exportable: bool) {
+ vis: &hir::Visibility, span: Span, exportable: bool,
+ mut applicability: Applicability) {
if !cx.access_levels.is_reachable(id) && *vis == hir::Visibility::Public {
+ if span.ctxt().outer().expn_info().is_some() {
+ applicability = Applicability::MaybeIncorrect;
+ }
let def_span = cx.tcx.sess.codemap().def_span(span);
let mut err = cx.struct_span_lint(UNREACHABLE_PUB, def_span,
&format!("unreachable `pub` {}", what));
- // visibility is token at start of declaration (can be macro
- // variable rather than literal `pub`)
+ // We are presuming that visibility is token at start of
+ // declaration (can be macro variable rather than literal `pub`)
let pub_span = cx.tcx.sess.codemap().span_until_char(def_span, ' ');
let replacement = if cx.tcx.features().crate_visibility_modifier {
"crate"
} else {
"pub(crate)"
}.to_owned();
- let app = if span.ctxt().outer().expn_info().is_none() {
- // even if macros aren't involved the suggestion
- // may be incorrect -- the user may have mistakenly
- // hidden it behind a private module and this lint is
- // a helpful way to catch that. However, we're trying
- // not to change the nature of the code with this lint
- // so it's marked as machine applicable.
- Applicability::MachineApplicable
- } else {
- Applicability::MaybeIncorrect
- };
- err.span_suggestion_with_applicability(pub_span, "consider restricting its visibility",
- replacement, app);
+ err.span_suggestion_with_applicability(pub_span,
+ "consider restricting its visibility",
+ replacement,
+ applicability);
if exportable {
err.help("or consider exporting it for use by other crates");
}
}
}
+
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnreachablePub {
fn check_item(&mut self, cx: &LateContext, item: &hir::Item) {
- self.perform_lint(cx, "item", item.id, &item.vis, item.span, true);
+ let applicability = match item.node {
+ // suggestion span-manipulation is inadequate for `pub use
+ // module::{item}` (Issue #50455)
+ hir::ItemUse(..) => Applicability::MaybeIncorrect,
+ _ => Applicability::MachineApplicable,
+ };
+ self.perform_lint(cx, "item", item.id, &item.vis, item.span, true, applicability);
}
fn check_foreign_item(&mut self, cx: &LateContext, foreign_item: &hir::ForeignItem) {
- self.perform_lint(cx, "item", foreign_item.id, &foreign_item.vis, foreign_item.span, true);
+ self.perform_lint(cx, "item", foreign_item.id, &foreign_item.vis,
+ foreign_item.span, true, Applicability::MachineApplicable);
}
fn check_struct_field(&mut self, cx: &LateContext, field: &hir::StructField) {
- self.perform_lint(cx, "field", field.id, &field.vis, field.span, false);
+ self.perform_lint(cx, "field", field.id, &field.vis, field.span, false,
+ Applicability::MachineApplicable);
}
fn check_impl_item(&mut self, cx: &LateContext, impl_item: &hir::ImplItem) {
- self.perform_lint(cx, "item", impl_item.id, &impl_item.vis, impl_item.span, false);
+ self.perform_lint(cx, "item", impl_item.id, &impl_item.vis, impl_item.span, false,
+ Applicability::MachineApplicable);
}
}
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ExternCrate {
fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
+ if !cx.tcx.features().extern_absolute_paths {
+ return
+ }
if let hir::ItemExternCrate(ref orig) = it.node {
if it.attrs.iter().any(|a| a.check_name("macro_use")) {
return
if let Some(orig) = orig {
err.span_suggestion(it.span, &help,
- format!("{}use {} as {}", pub_, orig, it.name));
+ format!("{}use {} as {};", pub_, orig, it.name));
} else {
err.span_suggestion(it.span, &help,
- format!("{}use {}", pub_, it.name));
+ format!("{}use {};", pub_, it.name));
}
} else {
err.span_suggestion(it.span, "remove it", "".into());
self.0 += 1;
}
}
+
+/// Lint for trait and lifetime bounds that don't depend on type parameters
+/// which either do nothing, or stop the item from being used.
+pub struct TrivialConstraints;
+
+declare_lint! {
+ TRIVIAL_BOUNDS,
+ Warn,
+ "these bounds don't depend on an type parameters"
+}
+
+impl LintPass for TrivialConstraints {
+ fn get_lints(&self) -> LintArray {
+ lint_array!(TRIVIAL_BOUNDS)
+ }
+}
+
+impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TrivialConstraints {
+ fn check_item(
+ &mut self,
+ cx: &LateContext<'a, 'tcx>,
+ item: &'tcx hir::Item,
+ ) {
+ use rustc::ty::fold::TypeFoldable;
+ use rustc::ty::Predicate::*;
+
+
+ if cx.tcx.features().trivial_bounds {
+ let def_id = cx.tcx.hir.local_def_id(item.id);
+ let predicates = cx.tcx.predicates_of(def_id);
+ for predicate in &predicates.predicates {
+ let predicate_kind_name = match *predicate {
+ Trait(..) => "Trait",
+ TypeOutlives(..) |
+ RegionOutlives(..) => "Lifetime",
+
+ // Ignore projections, as they can only be global
+ // if the trait bound is global
+ Projection(..) |
+ // Ignore bounds that a user can't type
+ WellFormed(..) |
+ ObjectSafe(..) |
+ ClosureKind(..) |
+ Subtype(..) |
+ ConstEvaluatable(..) => continue,
+ };
+ if predicate.is_global() {
+ cx.span_lint(
+ TRIVIAL_BOUNDS,
+ item.span,
+ &format!("{} bound {} does not depend on any type \
+ or lifetime parameters", predicate_kind_name, predicate),
+ );
+ }
+ }
+ }
+ }
+}