Commit dcccab56 authored by Mazdak Farrokhzad's avatar Mazdak Farrokhzad Committed by GitHub

Rollup merge of #59316 - flip1995:internal_lints_take_2, r=oli-obk

Internal lints take 2

cc #58701
cc #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
parents f8673e0a c81ce069
......@@ -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
......
......@@ -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)]
......
......@@ -9,6 +9,7 @@
test(attr(deny(warnings))))]
#![deny(rust_2018_idioms)]
#![cfg_attr(not(stage0), deny(internal))]
#![feature(nll)]
#![feature(rustc_private)]
......
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 {
......@@ -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 {}
......
......@@ -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;
......@@ -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
......
......@@ -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};
......@@ -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,
};
......@@ -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 \
......@@ -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,
}
}
......
......@@ -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)]
......
//! 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
}
......@@ -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;
......
......@@ -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) => {
......
......@@ -219,6 +219,11 @@ pub struct CommonTypes<'tcx> {
pub never: Ty<'tcx>,
pub err: Ty<'tcx>,
/// Dummy type used for the `Self` of a `TraitRef` created for converting
/// a trait object, and which gets removed in `ExistentialTraitRef`.
/// This type must not appear anywhere in other converted types.
pub trait_object_dummy_self: Ty<'tcx>,
pub re_empty: Region<'tcx>,
pub re_static: Region<'tcx>,
pub re_erased: Region<'tcx>,
......@@ -955,6 +960,8 @@ impl<'tcx> CommonTypes<'tcx> {
f32: mk(Float(ast::FloatTy::F32)),
f64: mk(Float(ast::FloatTy::F64)),
trait_object_dummy_self: mk(Infer(ty::FreshTy(0))),
re_empty: mk_region(RegionKind::ReEmpty),
re_static: mk_region(RegionKind::ReStatic),
re_erased: mk_region(RegionKind::ReErased),
......
#![cfg_attr(not(stage0), allow(usage_of_ty_tykind))]
pub use self::Variance::*;
pub use self::AssociatedItemContainer::*;
pub use self::BorrowKind::*;
......
#![allow(non_camel_case_types)]
use rustc_data_structures::sync::Lock;
use rustc_data_structures::{fx::FxHashMap, sync::Lock};
use std::cell::{RefCell, Cell};
use std::collections::HashMap;
use std::fmt::Debug;
use std::hash::{Hash, BuildHasher};
use std::hash::Hash;
use std::panic;
use std::env;
use std::time::{Duration, Instant};
......@@ -341,8 +340,8 @@ pub trait MemoizationMap {
where OP: FnOnce() -> Self::Value;
}
impl<K, V, S> MemoizationMap for RefCell<HashMap<K,V,S>>
where K: Hash+Eq+Clone, V: Clone, S: BuildHasher
impl<K, V> MemoizationMap for RefCell<FxHashMap<K,V>>
where K: Hash+Eq+Clone, V: Clone
{
type Key = K;
type Value = V;
......
......@@ -2,6 +2,7 @@
#![feature(rustc_private)]
#![deny(rust_2018_idioms)]
#![cfg_attr(not(stage0), deny(internal))]
pub mod expand;
......
......@@ -2,6 +2,7 @@
#![allow(non_camel_case_types)]
#![deny(rust_2018_idioms)]
#![cfg_attr(not(stage0), deny(internal))]
#![feature(nll)]
......
......@@ -14,6 +14,7 @@
#![allow(unused_attributes)]
#![allow(dead_code)]
#![deny(rust_2018_idioms)]
#![cfg_attr(not(stage0), deny(internal))]
#![allow(explicit_outlives_requirements)]
#![recursion_limit="256"]
......
......@@ -16,6 +16,7 @@
#![recursion_limit="256"]
#![deny(rust_2018_idioms)]
#![cfg_attr(not(stage0), deny(internal))]
#[macro_use]
extern crate rustc;
......
......@@ -17,6 +17,7 @@
#![recursion_limit="256"]
#![deny(rust_2018_idioms)]
#![cfg_attr(not(stage0), deny(internal))]
pub extern crate getopts;
#[cfg(unix)]
......
......@@ -6,6 +6,7 @@
#![feature(nll)]
#![feature(optin_builtin_traits)]
#![deny(rust_2018_idioms)]
#![cfg_attr(not(stage0), deny(internal))]
#[allow(unused_extern_crates)]
extern crate serialize as rustc_serialize; // used by deriving
......
......@@ -8,6 +8,7 @@
#![recursion_limit="256"]
#![deny(rust_2018_idioms)]
#![cfg_attr(not(stage0), deny(internal))]
#[macro_use] extern crate rustc;
#[allow(unused_extern_crates)]
......
......@@ -12,7 +12,6 @@ use rustc_data_structures::OnDrop;
use rustc_data_structures::sync::Lrc;
use rustc_data_structures::fx::{FxHashSet, FxHashMap};
use rustc_metadata::cstore::CStore;
use std::collections::HashSet;
use std::io::Write;
use std::path::PathBuf;
use std::result;
......
......@@ -7,6 +7,7 @@
#![cfg_attr(unix, feature(libc))]
#![deny(rust_2018_idioms)]
#![cfg_attr(not(stage0), deny(internal))]
#![allow(unused_imports)]
......
......@@ -21,7 +21,6 @@ use rustc_plugin;
use rustc_privacy;
use rustc_resolve;
use rustc_typeck;
use std::collections::HashSet;
use std::env;
use std::env::consts::{DLL_PREFIX, DLL_SUFFIX};
use std::io::{self, Write};
......@@ -109,6 +108,9 @@ pub fn create_session(
let codegen_backend = get_codegen_backend(&sess);
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
if sess.unstable_options() {
rustc_lint::register_internals(&mut sess.lint_store.borrow_mut(), Some(&sess));
}
let mut cfg = config::build_configuration(&sess, config::to_crate_config(cfg));
add_configuration(&mut cfg, &sess, &*codegen_backend);
......
......@@ -1036,7 +1036,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutableTransmutes {
let msg = "mutating transmuted &mut T from &T may cause undefined behavior, \
consider instead using an UnsafeCell";
match get_transmute_from_to(cx, expr) {
match get_transmute_from_to(cx, expr).map(|(ty1, ty2)| (&ty1.sty, &ty2.sty)) {
Some((&ty::Ref(_, _, from_mt), &ty::Ref(_, _, to_mt))) => {
if to_mt == hir::Mutability::MutMutable &&
from_mt == hir::Mutability::MutImmutable {
......@@ -1049,7 +1049,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutableTransmutes {
fn get_transmute_from_to<'a, 'tcx>
(cx: &LateContext<'a, 'tcx>,
expr: &hir::Expr)
-> Option<(&'tcx ty::TyKind<'tcx>, &'tcx ty::TyKind<'tcx>)> {
-> Option<(Ty<'tcx>, Ty<'tcx>)> {
let def = if let hir::ExprKind::Path(ref qpath) = expr.node {
cx.tables.qpath_def(qpath, expr.hir_id)
} else {
......@@ -1062,7 +1062,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutableTransmutes {
let sig = cx.tables.node_type(expr.hir_id).fn_sig(cx.tcx);
let from = sig.inputs().skip_binder()[0];
let to = *sig.output().skip_binder();
return Some((&from.sty, &to.sty));
return Some((from, to));
}
None
}
......
......@@ -20,6 +20,7 @@
#![recursion_limit="256"]
#![deny(rust_2018_idioms)]
#![cfg_attr(not(stage0), deny(internal))]
#[macro_use]
extern crate rustc;
......@@ -61,6 +62,7 @@ use nonstandard_style::*;
use builtin::*;
use types::*;
use unused::*;
use rustc::lint::internal::*;
/// Useful for other parts of the compiler.
pub use builtin::SoftLints;
......@@ -488,3 +490,18 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
store.register_removed("bad_repr",
"replaced with a generic attribute input check");
}
pub fn register_internals(store: &mut lint::LintStore, sess: Option<&Session>) {
store.register_early_pass(sess, false, false, box DefaultHashTypes::new());
store.register_late_pass(sess, false, false, false, box TyKindUsage);
store.register_group(
sess,
false,
"internal",
None,
vec![
LintId::of(DEFAULT_HASH_TYPES),
LintId::of(USAGE_OF_TY_TYKIND),
],
);
}
......@@ -104,7 +104,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
report_bin_hex_error(
cx,
e,
ty::Int(t),
attr::IntType::SignedInt(t),
repr_str,
v,
negative,
......@@ -159,7 +159,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
report_bin_hex_error(
cx,
e,
ty::Uint(t),
attr::IntType::UnsignedInt(t),
repr_str,
lit_val,
false,
......@@ -321,7 +321,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
//
// No suggestion for: `isize`, `usize`.
fn get_type_suggestion<'a>(
t: &ty::TyKind<'_>,
t: Ty<'_>,
val: u128,
negative: bool,
) -> Option<String> {
......@@ -347,14 +347,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
}
}
}
match t {
&ty::Int(i) => find_fit!(i, val, negative,
match t.sty {
ty::Int(i) => find_fit!(i, val, negative,
I8 => [U8] => [I16, I32, I64, I128],
I16 => [U16] => [I32, I64, I128],
I32 => [U32] => [I64, I128],
I64 => [U64] => [I128],
I128 => [U128] => []),
&ty::Uint(u) => find_fit!(u, val, negative,
ty::Uint(u) => find_fit!(u, val, negative,
U8 => [U8, U16, U32, U64, U128] => [],
U16 => [U16, U32, U64, U128] => [],
U32 => [U32, U64, U128] => [],
......@@ -367,25 +367,21 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
fn report_bin_hex_error(
cx: &LateContext<'_, '_>,
expr: &hir::Expr,
ty: ty::TyKind<'_>,
ty: attr::IntType,
repr_str: String,
val: u128,
negative: bool,
) {
let size = layout::Integer::from_attr(&cx.tcx, ty).size();
let (t, actually) = match ty {
ty::Int(t) => {
let ity = attr::IntType::SignedInt(t);
let size = layout::Integer::from_attr(&cx.tcx, ity).size();
attr::IntType::SignedInt(t) => {
let actually = sign_extend(val, size) as i128;
(format!("{:?}", t), actually.to_string())
}
ty::Uint(t) => {
let ity = attr::IntType::UnsignedInt(t);
let size = layout::Integer::from_attr(&cx.tcx, ity).size();
attr::IntType::UnsignedInt(t) => {
let actually = truncate(val, size);
(format!("{:?}", t), actually.to_string())
}
_ => bug!(),
};
let mut err = cx.struct_span_lint(
OVERFLOWING_LITERALS,
......@@ -398,7 +394,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
repr_str, val, t, actually, t
));
if let Some(sugg_ty) =
get_type_suggestion(&cx.tables.node_type(expr.hir_id).sty, val, negative)
get_type_suggestion(&cx.tables.node_type(expr.hir_id), val, negative)
{
if let Some(pos) = repr_str.chars().position(|c| c == 'i' || c == 'u') {
let (sans_suffix, _) = repr_str.split_at(pos);
......
......@@ -14,6 +14,7 @@
#![recursion_limit="256"]