Skip to content

Commit

Permalink
Rollup merge of rust-lang#59316 - flip1995:internal_lints_take_2, r=o…
Browse files Browse the repository at this point in the history
…li-obk

Internal lints take 2

cc rust-lang#58701
cc rust-lang#49509

TODO: Add `#![warn(internal)]` to crates (and fix violations)

Crates depending on `rustc_data_structures`

- [x] librustc_resolve
- [x] librustc_driver
- [x] librustc_passes
- [x] librustc_metadata
- [x] librustc_interface
- [x] librustc_save_analysis
- [x] librustc_lint
- [x] librustc
- [x] librustc_incremental
- [x] librustc_codegen_utils
- [x] libarena
- [x] librustc_target
- [x] librustc_allocator
- [x] librustc_privacy
- [x] librustc_traits
- [x] librustc_borrowck
- [x] libsyntax
- [x] librustc_codegen_ssa
- [x] libsyntax_ext
- [x] librustc_errors
- [x] librustc_mir
- [x] libsyntax_pos
- [x] librustc_typeck

Crates with `feature(rustc_private)`
Excluding crates, which are already in the list above. Also excluding tools and tests.

- [ ] ~~libstd~~
- [x] libfmt_macros
- [x] librustdoc

r? @oli-obk
  • Loading branch information
Centril committed Apr 3, 2019
2 parents f8673e0 + c81ce06 commit dcccab5
Show file tree
Hide file tree
Showing 58 changed files with 684 additions and 103 deletions.
5 changes: 5 additions & 0 deletions src/bootstrap/bin/rustc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,11 @@ fn main() {
}
}

// This is required for internal lints.
if stage != "0" {
cmd.arg("-Zunstable-options");
}

// Force all crates compiled by this compiler to (a) be unstable and (b)
// allow the `rustc_private` feature to link to other unstable crates
// also in the sysroot. We also do this for host crates, since those
Expand Down
1 change: 1 addition & 0 deletions src/libarena/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
test(no_crate_inject, attr(deny(warnings))))]

#![deny(rust_2018_idioms)]
#![cfg_attr(not(stage0), deny(internal))]

#![feature(alloc)]
#![feature(core_intrinsics)]
Expand Down
1 change: 1 addition & 0 deletions src/libfmt_macros/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
test(attr(deny(warnings))))]

#![deny(rust_2018_idioms)]
#![cfg_attr(not(stage0), deny(internal))]

#![feature(nll)]
#![feature(rustc_private)]
Expand Down
107 changes: 104 additions & 3 deletions src/librustc/hir/def_id.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use crate::ty;
use crate::ty::TyCtxt;
use crate::hir::map::definitions::FIRST_FREE_HIGH_DEF_INDEX;
use crate::ty::{self, print::Printer, subst::Kind, Ty, TyCtxt};
use crate::hir::map::definitions::{DisambiguatedDefPathData, FIRST_FREE_HIGH_DEF_INDEX};
use rustc_data_structures::indexed_vec::Idx;
use serialize;
use std::fmt;
use std::u32;
use syntax::symbol::{LocalInternedString, Symbol};

newtype_index! {
pub struct CrateId {
Expand Down Expand Up @@ -252,6 +252,107 @@ impl DefId {
format!("module `{}`", tcx.def_path_str(*self))
}
}

/// Check if a `DefId`'s path matches the given absolute type path usage.
// Uplifted from rust-lang/rust-clippy
pub fn match_path<'a, 'tcx>(self, tcx: TyCtxt<'a, 'tcx, 'tcx>, path: &[&str]) -> bool {
pub struct AbsolutePathPrinter<'a, 'tcx> {
pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
}

impl<'tcx> Printer<'tcx, 'tcx> for AbsolutePathPrinter<'_, 'tcx> {
type Error = !;

type Path = Vec<LocalInternedString>;
type Region = ();
type Type = ();
type DynExistential = ();

fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx> {
self.tcx
}

fn print_region(self, _region: ty::Region<'_>) -> Result<Self::Region, Self::Error> {
Ok(())
}

fn print_type(self, _ty: Ty<'tcx>) -> Result<Self::Type, Self::Error> {
Ok(())
}

fn print_dyn_existential(
self,
_predicates: &'tcx ty::List<ty::ExistentialPredicate<'tcx>>,
) -> Result<Self::DynExistential, Self::Error> {
Ok(())
}

fn path_crate(self, cnum: CrateNum) -> Result<Self::Path, Self::Error> {
Ok(vec![self.tcx.original_crate_name(cnum).as_str()])
}

fn path_qualified(
self,
self_ty: Ty<'tcx>,
trait_ref: Option<ty::TraitRef<'tcx>>,
) -> Result<Self::Path, Self::Error> {
if trait_ref.is_none() {
if let ty::Adt(def, substs) = self_ty.sty {
return self.print_def_path(def.did, substs);
}
}

// This shouldn't ever be needed, but just in case:
Ok(vec![match trait_ref {
Some(trait_ref) => Symbol::intern(&format!("{:?}", trait_ref)).as_str(),
None => Symbol::intern(&format!("<{}>", self_ty)).as_str(),
}])
}

fn path_append_impl(
self,
print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
_disambiguated_data: &DisambiguatedDefPathData,
self_ty: Ty<'tcx>,
trait_ref: Option<ty::TraitRef<'tcx>>,
) -> Result<Self::Path, Self::Error> {
let mut path = print_prefix(self)?;

// This shouldn't ever be needed, but just in case:
path.push(match trait_ref {
Some(trait_ref) => {
Symbol::intern(&format!("<impl {} for {}>", trait_ref, self_ty)).as_str()
},
None => Symbol::intern(&format!("<impl {}>", self_ty)).as_str(),
});

Ok(path)
}

fn path_append(
self,
print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
disambiguated_data: &DisambiguatedDefPathData,
) -> Result<Self::Path, Self::Error> {
let mut path = print_prefix(self)?;
path.push(disambiguated_data.data.as_interned_str().as_str());
Ok(path)
}

fn path_generic_args(
self,
print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
_args: &[Kind<'tcx>],
) -> Result<Self::Path, Self::Error> {
print_prefix(self)
}
}

let names = AbsolutePathPrinter { tcx }.print_def_path(self, &[]).unwrap();

names.len() == path.len()
&& names.into_iter().zip(path.iter()).all(|(a, &b)| *a == *b)
}
}

impl serialize::UseSpecializedEncodable for DefId {}
Expand Down
8 changes: 3 additions & 5 deletions src/librustc/ich/hcx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ use crate::session::Session;

use std::cmp::Ord;
use std::hash as std_hash;
use std::collections::HashMap;
use std::cell::RefCell;

use syntax::ast;
Expand Down Expand Up @@ -394,13 +393,12 @@ impl<'a> HashStable<StableHashingContext<'a>> for DelimSpan {
}
}

pub fn hash_stable_trait_impls<'a, 'gcx, W, R>(
pub fn hash_stable_trait_impls<'a, 'gcx, W>(
hcx: &mut StableHashingContext<'a>,
hasher: &mut StableHasher<W>,
blanket_impls: &[DefId],
non_blanket_impls: &HashMap<fast_reject::SimplifiedType, Vec<DefId>, R>)
where W: StableHasherResult,
R: std_hash::BuildHasher,
non_blanket_impls: &FxHashMap<fast_reject::SimplifiedType, Vec<DefId>>)
where W: StableHasherResult
{
{
let mut blanket_impls: SmallVec<[_; 8]> = blanket_impls
Expand Down
22 changes: 11 additions & 11 deletions src/librustc/infer/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ use crate::hir::Node;
use crate::middle::region;
use crate::traits::{ObligationCause, ObligationCauseCode};
use crate::ty::error::TypeError;
use crate::ty::{self, subst::{Subst, SubstsRef}, Region, Ty, TyCtxt, TyKind, TypeFoldable};
use crate::ty::{self, subst::{Subst, SubstsRef}, Region, Ty, TyCtxt, TypeFoldable};
use errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString};
use std::{cmp, fmt};
use syntax_pos::{Pos, Span};
Expand Down Expand Up @@ -1094,14 +1094,14 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
(_, false, _) => {
if let Some(exp_found) = exp_found {
let (def_id, ret_ty) = match exp_found.found.sty {
TyKind::FnDef(def, _) => {
ty::FnDef(def, _) => {
(Some(def), Some(self.tcx.fn_sig(def).output()))
}
_ => (None, None),
};

let exp_is_struct = match exp_found.expected.sty {
TyKind::Adt(def, _) => def.is_struct(),
ty::Adt(def, _) => def.is_struct(),
_ => false,
};

Expand Down Expand Up @@ -1140,8 +1140,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
diag: &mut DiagnosticBuilder<'tcx>,
) {
match (&exp_found.expected.sty, &exp_found.found.sty) {
(TyKind::Adt(exp_def, exp_substs), TyKind::Ref(_, found_ty, _)) => {
if let TyKind::Adt(found_def, found_substs) = found_ty.sty {
(ty::Adt(exp_def, exp_substs), ty::Ref(_, found_ty, _)) => {
if let ty::Adt(found_def, found_substs) = found_ty.sty {
let path_str = format!("{:?}", exp_def);
if exp_def == &found_def {
let opt_msg = "you can convert from `&Option<T>` to `Option<&T>` using \
Expand All @@ -1164,17 +1164,17 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
let mut show_suggestion = true;
for (exp_ty, found_ty) in exp_substs.types().zip(found_substs.types()) {
match exp_ty.sty {
TyKind::Ref(_, exp_ty, _) => {
ty::Ref(_, exp_ty, _) => {
match (&exp_ty.sty, &found_ty.sty) {
(_, TyKind::Param(_)) |
(_, TyKind::Infer(_)) |
(TyKind::Param(_), _) |
(TyKind::Infer(_), _) => {}
(_, ty::Param(_)) |
(_, ty::Infer(_)) |
(ty::Param(_), _) |
(ty::Infer(_), _) => {}
_ if ty::TyS::same_type(exp_ty, found_ty) => {}
_ => show_suggestion = false,
};
}
TyKind::Param(_) | TyKind::Infer(_) => {}
ty::Param(_) | ty::Infer(_) => {}
_ => show_suggestion = false,
}
}
Expand Down
1 change: 1 addition & 0 deletions src/librustc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]

#![deny(rust_2018_idioms)]
#![cfg_attr(not(stage0), deny(internal))]
#![allow(explicit_outlives_requirements)]

#![feature(arbitrary_self_types)]
Expand Down
127 changes: 127 additions & 0 deletions src/librustc/lint/internal.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
//! Some lints that are only useful in the compiler or crates that use compiler internals, such as
//! Clippy.

use crate::hir::{HirId, Path, PathSegment, QPath, Ty, TyKind};
use crate::lint::{
EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintArray, LintContext, LintPass,
};
use errors::Applicability;
use rustc_data_structures::fx::FxHashMap;
use syntax::ast::Ident;

declare_lint! {
pub DEFAULT_HASH_TYPES,
Allow,
"forbid HashMap and HashSet and suggest the FxHash* variants"
}

pub struct DefaultHashTypes {
map: FxHashMap<String, String>,
}

impl DefaultHashTypes {
pub fn new() -> Self {
let mut map = FxHashMap::default();
map.insert("HashMap".to_string(), "FxHashMap".to_string());
map.insert("HashSet".to_string(), "FxHashSet".to_string());
Self { map }
}
}

impl LintPass for DefaultHashTypes {
fn get_lints(&self) -> LintArray {
lint_array!(DEFAULT_HASH_TYPES)
}

fn name(&self) -> &'static str {
"DefaultHashTypes"
}
}

impl EarlyLintPass for DefaultHashTypes {
fn check_ident(&mut self, cx: &EarlyContext<'_>, ident: Ident) {
let ident_string = ident.to_string();
if let Some(replace) = self.map.get(&ident_string) {
let msg = format!(
"Prefer {} over {}, it has better performance",
replace, ident_string
);
let mut db = cx.struct_span_lint(DEFAULT_HASH_TYPES, ident.span, &msg);
db.span_suggestion(
ident.span,
"use",
replace.to_string(),
Applicability::MaybeIncorrect, // FxHashMap, ... needs another import
);
db.note(&format!(
"a `use rustc_data_structures::fx::{}` may be necessary",
replace
))
.emit();
}
}
}

declare_lint! {
pub USAGE_OF_TY_TYKIND,
Allow,
"Usage of `ty::TyKind` outside of the `ty::sty` module"
}

pub struct TyKindUsage;

impl LintPass for TyKindUsage {
fn get_lints(&self) -> LintArray {
lint_array!(USAGE_OF_TY_TYKIND)
}

fn name(&self) -> &'static str {
"TyKindUsage"
}
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TyKindUsage {
fn check_path(&mut self, cx: &LateContext<'_, '_>, path: &'tcx Path, _: HirId) {
let segments = path.segments.iter().rev().skip(1).rev();

if let Some(last) = segments.last() {
let span = path.span.with_hi(last.ident.span.hi());
if lint_ty_kind_usage(cx, last) {
cx.struct_span_lint(USAGE_OF_TY_TYKIND, span, "usage of `ty::TyKind::<kind>`")
.span_suggestion(
span,
"try using ty::<kind> directly",
"ty".to_string(),
Applicability::MaybeIncorrect, // ty maybe needs an import
)
.emit();
}
}
}

fn check_ty(&mut self, cx: &LateContext<'_, '_>, ty: &'tcx Ty) {
if let TyKind::Path(qpath) = &ty.node {
if let QPath::Resolved(_, path) = qpath {
if let Some(last) = path.segments.iter().last() {
if lint_ty_kind_usage(cx, last) {
cx.struct_span_lint(USAGE_OF_TY_TYKIND, path.span, "usage of `ty::TyKind`")
.help("try using `ty::Ty` instead")
.emit();
}
}
}
}
}
}

fn lint_ty_kind_usage(cx: &LateContext<'_, '_>, segment: &PathSegment) -> bool {
if segment.ident.as_str() == "TyKind" {
if let Some(def) = segment.def {
if let Some(did) = def.opt_def_id() {
return did.match_path(cx.tcx, &["rustc", "ty", "sty", "TyKind"]);
}
}
}

false
}
1 change: 1 addition & 0 deletions src/librustc/lint/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -574,6 +574,7 @@ impl_stable_hash_for!(enum self::LintSource {
pub type LevelSource = (Level, LintSource);

pub mod builtin;
pub mod internal;
mod context;
mod levels;

Expand Down
2 changes: 1 addition & 1 deletion src/librustc/mir/tcx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> {
pub fn field_ty(self, tcx: TyCtxt<'a, 'gcx, 'tcx>, f: &Field) -> Ty<'tcx>
{
let answer = match self.ty.sty {
ty::TyKind::Adt(adt_def, substs) => {
ty::Adt(adt_def, substs) => {
let variant_def = match self.variant_index {
None => adt_def.non_enum_variant(),
Some(variant_index) => {
Expand Down
Loading

0 comments on commit dcccab5

Please sign in to comment.