diff --git a/Cargo.lock b/Cargo.lock index 9d726b240da93..37b3caeddb3b1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4345,6 +4345,7 @@ dependencies = [ "bitflags", "rustc_data_structures", "rustc_index", + "rustc_macros", "rustc_serialize", ] diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs index beff84fb2e217..5702832bcb67d 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/src/constant.rs @@ -134,11 +134,9 @@ pub(crate) fn codegen_constant<'tcx>( { Ok(const_val) => const_val, Err(_) => { - if promoted.is_none() { - fx.tcx - .sess - .span_err(constant.span, "erroneous constant encountered"); - } + fx.tcx + .sess + .span_err(constant.span, "erroneous constant encountered"); return crate::trap::trap_unreachable_ret_value( fx, fx.layout_of(const_.ty), diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index 6e4f3bf2898d8..f31c58b92e407 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -83,7 +83,6 @@ mod vtable; mod prelude { pub(crate) use std::convert::{TryFrom, TryInto}; - pub(crate) use rustc_ast::ast::{FloatTy, IntTy, UintTy}; pub(crate) use rustc_span::Span; pub(crate) use rustc_hir::def_id::{DefId, LOCAL_CRATE}; @@ -91,7 +90,7 @@ mod prelude { pub(crate) use rustc_middle::mir::{self, *}; pub(crate) use rustc_middle::ty::layout::{self, TyAndLayout}; pub(crate) use rustc_middle::ty::{ - self, FnSig, Instance, InstanceDef, ParamEnv, Ty, TyCtxt, TypeAndMut, TypeFoldable, + self, FloatTy, FnSig, Instance, InstanceDef, IntTy, ParamEnv, Ty, TyCtxt, TypeAndMut, TypeFoldable, UintTy, }; pub(crate) use rustc_target::abi::{Abi, LayoutOf, Scalar, Size, VariantIdx}; diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index f122fa14e70be..d2f4d3edc2207 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -304,9 +304,8 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { lhs: Self::Value, rhs: Self::Value, ) -> (Self::Value, Self::Value) { - use rustc_ast::IntTy::*; - use rustc_ast::UintTy::*; use rustc_middle::ty::{Int, Uint}; + use rustc_middle::ty::{IntTy::*, UintTy::*}; let new_kind = match ty.kind() { Int(t @ Isize) => Int(t.normalize(self.tcx.sess.target.pointer_width)), diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index b9ae796325023..3a4e1492af337 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -18,7 +18,6 @@ use crate::llvm::debuginfo::{ }; use crate::value::Value; -use rustc_ast as ast; use rustc_codegen_ssa::traits::*; use rustc_data_structures::const_cstr; use rustc_data_structures::fingerprint::Fingerprint; @@ -830,37 +829,37 @@ trait MsvcBasicName { fn msvc_basic_name(self) -> &'static str; } -impl MsvcBasicName for ast::IntTy { +impl MsvcBasicName for ty::IntTy { fn msvc_basic_name(self) -> &'static str { match self { - ast::IntTy::Isize => "ptrdiff_t", - ast::IntTy::I8 => "__int8", - ast::IntTy::I16 => "__int16", - ast::IntTy::I32 => "__int32", - ast::IntTy::I64 => "__int64", - ast::IntTy::I128 => "__int128", + ty::IntTy::Isize => "ptrdiff_t", + ty::IntTy::I8 => "__int8", + ty::IntTy::I16 => "__int16", + ty::IntTy::I32 => "__int32", + ty::IntTy::I64 => "__int64", + ty::IntTy::I128 => "__int128", } } } -impl MsvcBasicName for ast::UintTy { +impl MsvcBasicName for ty::UintTy { fn msvc_basic_name(self) -> &'static str { match self { - ast::UintTy::Usize => "size_t", - ast::UintTy::U8 => "unsigned __int8", - ast::UintTy::U16 => "unsigned __int16", - ast::UintTy::U32 => "unsigned __int32", - ast::UintTy::U64 => "unsigned __int64", - ast::UintTy::U128 => "unsigned __int128", + ty::UintTy::Usize => "size_t", + ty::UintTy::U8 => "unsigned __int8", + ty::UintTy::U16 => "unsigned __int16", + ty::UintTy::U32 => "unsigned __int32", + ty::UintTy::U64 => "unsigned __int64", + ty::UintTy::U128 => "unsigned __int128", } } } -impl MsvcBasicName for ast::FloatTy { +impl MsvcBasicName for ty::FloatTy { fn msvc_basic_name(self) -> &'static str { match self { - ast::FloatTy::F32 => "float", - ast::FloatTy::F64 => "double", + ty::FloatTy::F32 => "float", + ty::FloatTy::F64 => "double", } } } diff --git a/compiler/rustc_codegen_llvm/src/type_.rs b/compiler/rustc_codegen_llvm/src/type_.rs index a43724fd49599..8fd0caae479a8 100644 --- a/compiler/rustc_codegen_llvm/src/type_.rs +++ b/compiler/rustc_codegen_llvm/src/type_.rs @@ -7,13 +7,12 @@ use crate::llvm; use crate::llvm::{Bool, False, True}; use crate::type_of::LayoutLlvmExt; use crate::value::Value; -use rustc_ast as ast; use rustc_codegen_ssa::common::TypeKind; use rustc_codegen_ssa::traits::*; use rustc_data_structures::small_c_str::SmallCStr; use rustc_middle::bug; use rustc_middle::ty::layout::TyAndLayout; -use rustc_middle::ty::Ty; +use rustc_middle::ty::{self, Ty}; use rustc_target::abi::call::{CastTarget, FnAbi, Reg}; use rustc_target::abi::{AddressSpace, Align, Integer, Size}; @@ -80,32 +79,32 @@ impl CodegenCx<'ll, 'tcx> { self.type_i8() } - crate fn type_int_from_ty(&self, t: ast::IntTy) -> &'ll Type { + crate fn type_int_from_ty(&self, t: ty::IntTy) -> &'ll Type { match t { - ast::IntTy::Isize => self.type_isize(), - ast::IntTy::I8 => self.type_i8(), - ast::IntTy::I16 => self.type_i16(), - ast::IntTy::I32 => self.type_i32(), - ast::IntTy::I64 => self.type_i64(), - ast::IntTy::I128 => self.type_i128(), + ty::IntTy::Isize => self.type_isize(), + ty::IntTy::I8 => self.type_i8(), + ty::IntTy::I16 => self.type_i16(), + ty::IntTy::I32 => self.type_i32(), + ty::IntTy::I64 => self.type_i64(), + ty::IntTy::I128 => self.type_i128(), } } - crate fn type_uint_from_ty(&self, t: ast::UintTy) -> &'ll Type { + crate fn type_uint_from_ty(&self, t: ty::UintTy) -> &'ll Type { match t { - ast::UintTy::Usize => self.type_isize(), - ast::UintTy::U8 => self.type_i8(), - ast::UintTy::U16 => self.type_i16(), - ast::UintTy::U32 => self.type_i32(), - ast::UintTy::U64 => self.type_i64(), - ast::UintTy::U128 => self.type_i128(), + ty::UintTy::Usize => self.type_isize(), + ty::UintTy::U8 => self.type_i8(), + ty::UintTy::U16 => self.type_i16(), + ty::UintTy::U32 => self.type_i32(), + ty::UintTy::U64 => self.type_i64(), + ty::UintTy::U128 => self.type_i128(), } } - crate fn type_float_from_ty(&self, t: ast::FloatTy) -> &'ll Type { + crate fn type_float_from_ty(&self, t: ty::FloatTy) -> &'ll Type { match t { - ast::FloatTy::F32 => self.type_f32(), - ast::FloatTy::F64 => self.type_f64(), + ty::FloatTy::F32 => self.type_f32(), + ty::FloatTy::F64 => self.type_f64(), } } diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index ecac05fd95572..c821908167870 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -875,20 +875,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { ty::Uint(_) => value.to_string(), ty::Int(int_ty) => { match int_ty.normalize(bx.tcx().sess.target.pointer_width) { - ast::IntTy::I8 => (value as i8).to_string(), - ast::IntTy::I16 => (value as i16).to_string(), - ast::IntTy::I32 => (value as i32).to_string(), - ast::IntTy::I64 => (value as i64).to_string(), - ast::IntTy::I128 => (value as i128).to_string(), - ast::IntTy::Isize => unreachable!(), + ty::IntTy::I8 => (value as i8).to_string(), + ty::IntTy::I16 => (value as i16).to_string(), + ty::IntTy::I32 => (value as i32).to_string(), + ty::IntTy::I64 => (value as i64).to_string(), + ty::IntTy::I128 => (value as i128).to_string(), + ty::IntTy::Isize => unreachable!(), } } - ty::Float(ast::FloatTy::F32) => { - f32::from_bits(value as u32).to_string() - } - ty::Float(ast::FloatTy::F64) => { - f64::from_bits(value as u64).to_string() - } + ty::Float(ty::FloatTy::F32) => f32::from_bits(value as u32).to_string(), + ty::Float(ty::FloatTy::F64) => f64::from_bits(value as u64).to_string(), _ => span_bug!(span, "asm const has bad type {}", ty), }; InlineAsmOperandRef::Const { string } diff --git a/compiler/rustc_codegen_ssa/src/mir/constant.rs b/compiler/rustc_codegen_ssa/src/mir/constant.rs index 3a85c268e0ea9..b79a221a0e74a 100644 --- a/compiler/rustc_codegen_ssa/src/mir/constant.rs +++ b/compiler/rustc_codegen_ssa/src/mir/constant.rs @@ -30,12 +30,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { .tcx() .const_eval_resolve(ty::ParamEnv::reveal_all(), def, substs, promoted, None) .map_err(|err| { - if promoted.is_none() { - self.cx - .tcx() - .sess - .span_err(constant.span, "erroneous constant encountered"); - } + self.cx.tcx().sess.span_err(constant.span, "erroneous constant encountered"); err }), ty::ConstKind::Value(value) => Ok(value), diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index 285140060be45..8a009b66b593e 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -188,8 +188,10 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( fx.per_local_var_debug_info = fx.compute_per_local_var_debug_info(&mut bx); + let mut all_consts_ok = true; for const_ in &mir.required_consts { if let Err(err) = fx.eval_mir_constant(const_) { + all_consts_ok = false; match err { // errored or at least linted ErrorHandled::Reported(ErrorReported) | ErrorHandled::Linted => {} @@ -199,6 +201,25 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( } } } + if !all_consts_ok { + // There is no delay_span_bug here, we just have to rely on a hard error actually having + // been raised. + bx.abort(); + // `abort` does not terminate the block, so we still need to generate + // an `unreachable` terminator after it. + bx.unreachable(); + // We also have to delete all the other basic blocks again... + for bb in mir.basic_blocks().indices() { + if bb != mir::START_BLOCK { + unsafe { + bx.delete_basic_block(fx.blocks[bb]); + } + } + } + // FIXME: Can we somehow avoid all this by evaluating the consts before creating the basic + // blocks? The tricky part is doing that without duplicating `fx.eval_mir_constant`. + return; + } let memory_locals = analyze::non_ssa_locals(&fx); diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs index 08a4ae3962bee..25e84c38ed315 100644 --- a/compiler/rustc_codegen_ssa/src/mir/operand.rs +++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs @@ -6,9 +6,8 @@ use crate::glue; use crate::traits::*; use crate::MemFlags; -use rustc_errors::ErrorReported; use rustc_middle::mir; -use rustc_middle::mir::interpret::{ConstValue, ErrorHandled, Pointer, Scalar}; +use rustc_middle::mir::interpret::{ConstValue, Pointer, Scalar}; use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::ty::Ty; use rustc_target::abi::{Abi, Align, LayoutOf, Size}; @@ -439,25 +438,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } mir::Operand::Constant(ref constant) => { - self.eval_mir_constant_to_operand(bx, constant).unwrap_or_else(|err| { - match err { - // errored or at least linted - ErrorHandled::Reported(ErrorReported) | ErrorHandled::Linted => {} - ErrorHandled::TooGeneric => { - bug!("codegen encountered polymorphic constant") - } - } - // Allow RalfJ to sleep soundly knowing that even refactorings that remove - // the above error (or silence it under some conditions) will not cause UB. - bx.abort(); - // We still have to return an operand but it doesn't matter, - // this code is unreachable. - let ty = self.monomorphize(constant.literal.ty); - let layout = bx.cx().layout_of(ty); - bx.load_operand(PlaceRef::new_sized( - bx.cx().const_undef(bx.cx().type_ptr_to(bx.cx().backend_type(layout))), - layout, - )) + // This cannot fail because we checked all required_consts in advance. + self.eval_mir_constant_to_operand(bx, constant).unwrap_or_else(|_err| { + span_bug!(constant.span, "erroneous constant not captured by required_consts") }) } } diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 2f43940a9dcbb..08543d1622a7d 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -929,7 +929,9 @@ pub struct ExtCtxt<'a> { pub force_mode: bool, pub expansions: FxHashMap>, /// Called directly after having parsed an external `mod foo;` in expansion. - pub(super) extern_mod_loaded: Option<&'a dyn Fn(&ast::Crate)>, + /// + /// `Ident` is the module name. + pub(super) extern_mod_loaded: Option<&'a dyn Fn(&ast::Crate, Ident)>, } impl<'a> ExtCtxt<'a> { @@ -937,7 +939,7 @@ impl<'a> ExtCtxt<'a> { sess: &'a Session, ecfg: expand::ExpansionConfig<'a>, resolver: &'a mut dyn ResolverExpand, - extern_mod_loaded: Option<&'a dyn Fn(&ast::Crate)>, + extern_mod_loaded: Option<&'a dyn Fn(&ast::Crate, Ident)>, ) -> ExtCtxt<'a> { ExtCtxt { sess, diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 5d398935ce815..50832d5edbfc5 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -1407,7 +1407,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { proc_macros: vec![], }; if let Some(extern_mod_loaded) = self.cx.extern_mod_loaded { - extern_mod_loaded(&krate); + extern_mod_loaded(&krate, ident); } *old_mod = krate.module; diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs index b344086e95e77..e6fc31f0e4fd4 100644 --- a/compiler/rustc_infer/src/infer/combine.rs +++ b/compiler/rustc_infer/src/infer/combine.rs @@ -34,7 +34,6 @@ use super::{InferCtxt, MiscVariable, TypeTrace}; use crate::traits::{Obligation, PredicateObligations}; -use rustc_ast as ast; use rustc_data_structures::sso::SsoHashMap; use rustc_hir::def_id::DefId; use rustc_middle::traits::ObligationCause; @@ -281,7 +280,7 @@ impl<'infcx, 'tcx> InferCtxt<'infcx, 'tcx> { &self, vid_is_expected: bool, vid: ty::FloatVid, - val: ast::FloatTy, + val: ty::FloatTy, ) -> RelateResult<'tcx, Ty<'tcx>> { self.inner .borrow_mut() @@ -543,10 +542,6 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> { true } - fn visit_ct_substs(&self) -> bool { - true - } - fn binders( &mut self, a: ty::Binder, @@ -737,6 +732,16 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> { } } } + ty::ConstKind::Unevaluated(def, substs, promoted) + if self.tcx().lazy_normalization() => + { + assert_eq!(promoted, None); + let substs = self.relate_with_variance(ty::Variance::Invariant, substs, substs)?; + Ok(self.tcx().mk_const(ty::Const { + ty: c.ty, + val: ty::ConstKind::Unevaluated(def, substs, promoted), + })) + } _ => relate::super_relate_consts(self, c, c), } } @@ -822,10 +827,6 @@ impl TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> { true } - fn visit_ct_substs(&self) -> bool { - true - } - fn relate_with_variance>( &mut self, _variance: ty::Variance, @@ -959,6 +960,16 @@ impl TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> { } } } + ty::ConstKind::Unevaluated(def, substs, promoted) + if self.tcx().lazy_normalization() => + { + assert_eq!(promoted, None); + let substs = self.relate_with_variance(ty::Variance::Invariant, substs, substs)?; + Ok(self.tcx().mk_const(ty::Const { + ty: c.ty, + val: ty::ConstKind::Unevaluated(def, substs, promoted), + })) + } _ => relate::super_relate_consts(self, c, c), } } diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 7031234e1089d..56aa3939b22dc 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -33,7 +33,7 @@ use rustc_session::lint; use rustc_session::output::{filename_for_input, filename_for_metadata}; use rustc_session::search_paths::PathKind; use rustc_session::Session; -use rustc_span::symbol::Symbol; +use rustc_span::symbol::{Ident, Symbol}; use rustc_span::{FileName, RealFileName}; use rustc_trait_selection::traits; use rustc_typeck as typeck; @@ -211,8 +211,13 @@ pub fn register_plugins<'a>( Ok((krate, lint_store)) } -fn pre_expansion_lint(sess: &Session, lint_store: &LintStore, krate: &ast::Crate) { - sess.time("pre_AST_expansion_lint_checks", || { +fn pre_expansion_lint( + sess: &Session, + lint_store: &LintStore, + krate: &ast::Crate, + crate_name: &str, +) { + sess.prof.generic_activity_with_arg("pre_AST_expansion_lint_checks", crate_name).run(|| { rustc_lint::check_ast_crate( sess, lint_store, @@ -233,7 +238,7 @@ fn configure_and_expand_inner<'a>( metadata_loader: &'a MetadataLoaderDyn, ) -> Result<(ast::Crate, Resolver<'a>)> { tracing::trace!("configure_and_expand_inner"); - pre_expansion_lint(sess, lint_store, &krate); + pre_expansion_lint(sess, lint_store, &krate, crate_name); let mut resolver = Resolver::new(sess, &krate, crate_name, metadata_loader, &resolver_arenas); rustc_builtin_macros::register_builtin_macros(&mut resolver); @@ -295,7 +300,9 @@ fn configure_and_expand_inner<'a>( ..rustc_expand::expand::ExpansionConfig::default(crate_name.to_string()) }; - let extern_mod_loaded = |k: &ast::Crate| pre_expansion_lint(sess, lint_store, k); + let extern_mod_loaded = |k: &ast::Crate, ident: Ident| { + pre_expansion_lint(sess, lint_store, k, &*ident.name.as_str()) + }; let mut ecx = ExtCtxt::new(&sess, cfg, &mut resolver, Some(&extern_mod_loaded)); // Expand macros now! diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index b17765998807f..8bd9dad785c4b 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -746,6 +746,14 @@ impl<'tcx> LateContext<'tcx> { hir::QPath::Resolved(_, ref path) => path.res, hir::QPath::TypeRelative(..) | hir::QPath::LangItem(..) => self .maybe_typeck_results() + .filter(|typeck_results| typeck_results.hir_owner == id.owner) + .or_else(|| { + if self.tcx.has_typeck_results(id.owner.to_def_id()) { + Some(self.tcx.typeck(id.owner)) + } else { + None + } + }) .and_then(|typeck_results| typeck_results.type_dependent_def(id)) .map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)), } diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs index 015e109871182..3821a393efb8b 100644 --- a/compiler/rustc_lint/src/late.rs +++ b/compiler/rustc_lint/src/late.rs @@ -140,6 +140,8 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) { let generics = self.context.generics.take(); self.context.generics = it.kind.generics(); + let old_cached_typeck_results = self.context.cached_typeck_results.take(); + let old_enclosing_body = self.context.enclosing_body.take(); self.with_lint_attrs(it.hir_id, &it.attrs, |cx| { cx.with_param_env(it.hir_id, |cx| { lint_callback!(cx, check_item, it); @@ -147,6 +149,8 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas lint_callback!(cx, check_item_post, it); }); }); + self.context.enclosing_body = old_enclosing_body; + self.context.cached_typeck_results.set(old_cached_typeck_results); self.context.generics = generics; } diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 424f91b3f883e..1e879d2937060 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -168,25 +168,25 @@ fn lint_overflowing_range_endpoint<'tcx>( // For `isize` & `usize`, be conservative with the warnings, so that the // warnings are consistent between 32- and 64-bit platforms. -fn int_ty_range(int_ty: ast::IntTy) -> (i128, i128) { +fn int_ty_range(int_ty: ty::IntTy) -> (i128, i128) { match int_ty { - ast::IntTy::Isize => (i64::MIN.into(), i64::MAX.into()), - ast::IntTy::I8 => (i8::MIN.into(), i8::MAX.into()), - ast::IntTy::I16 => (i16::MIN.into(), i16::MAX.into()), - ast::IntTy::I32 => (i32::MIN.into(), i32::MAX.into()), - ast::IntTy::I64 => (i64::MIN.into(), i64::MAX.into()), - ast::IntTy::I128 => (i128::MIN, i128::MAX), + ty::IntTy::Isize => (i64::MIN.into(), i64::MAX.into()), + ty::IntTy::I8 => (i8::MIN.into(), i8::MAX.into()), + ty::IntTy::I16 => (i16::MIN.into(), i16::MAX.into()), + ty::IntTy::I32 => (i32::MIN.into(), i32::MAX.into()), + ty::IntTy::I64 => (i64::MIN.into(), i64::MAX.into()), + ty::IntTy::I128 => (i128::MIN, i128::MAX), } } -fn uint_ty_range(uint_ty: ast::UintTy) -> (u128, u128) { +fn uint_ty_range(uint_ty: ty::UintTy) -> (u128, u128) { let max = match uint_ty { - ast::UintTy::Usize => u64::MAX.into(), - ast::UintTy::U8 => u8::MAX.into(), - ast::UintTy::U16 => u16::MAX.into(), - ast::UintTy::U32 => u32::MAX.into(), - ast::UintTy::U64 => u64::MAX.into(), - ast::UintTy::U128 => u128::MAX, + ty::UintTy::Usize => u64::MAX.into(), + ty::UintTy::U8 => u8::MAX.into(), + ty::UintTy::U16 => u16::MAX.into(), + ty::UintTy::U32 => u32::MAX.into(), + ty::UintTy::U64 => u64::MAX.into(), + ty::UintTy::U128 => u128::MAX, }; (0, max) } @@ -258,8 +258,8 @@ fn report_bin_hex_error( // // No suggestion for: `isize`, `usize`. fn get_type_suggestion(t: Ty<'_>, val: u128, negative: bool) -> Option<&'static str> { - use rustc_ast::IntTy::*; - use rustc_ast::UintTy::*; + use ty::IntTy::*; + use ty::UintTy::*; macro_rules! find_fit { ($ty:expr, $val:expr, $negative:expr, $($type:ident => [$($utypes:expr),*] => [$($itypes:expr),*]),+) => { @@ -302,7 +302,7 @@ fn lint_int_literal<'tcx>( type_limits: &TypeLimits, e: &'tcx hir::Expr<'tcx>, lit: &hir::Lit, - t: ast::IntTy, + t: ty::IntTy, v: u128, ) { let int_type = t.normalize(cx.sess().target.pointer_width); @@ -314,7 +314,14 @@ fn lint_int_literal<'tcx>( // avoiding use of -min to prevent overflow/panic if (negative && v > max + 1) || (!negative && v > max) { if let Some(repr_str) = get_bin_hex_repr(cx, lit) { - report_bin_hex_error(cx, e, attr::IntType::SignedInt(t), repr_str, v, negative); + report_bin_hex_error( + cx, + e, + attr::IntType::SignedInt(ty::ast_int_ty(t)), + repr_str, + v, + negative, + ); return; } @@ -351,7 +358,7 @@ fn lint_uint_literal<'tcx>( cx: &LateContext<'tcx>, e: &'tcx hir::Expr<'tcx>, lit: &hir::Lit, - t: ast::UintTy, + t: ty::UintTy, ) { let uint_type = t.normalize(cx.sess().target.pointer_width); let (min, max) = uint_ty_range(uint_type); @@ -391,7 +398,14 @@ fn lint_uint_literal<'tcx>( } } if let Some(repr_str) = get_bin_hex_repr(cx, lit) { - report_bin_hex_error(cx, e, attr::IntType::UnsignedInt(t), repr_str, lit_val, false); + report_bin_hex_error( + cx, + e, + attr::IntType::UnsignedInt(ty::ast_uint_ty(t)), + repr_str, + lit_val, + false, + ); return; } cx.struct_span_lint(OVERFLOWING_LITERALS, e.span, |lint| { @@ -430,8 +444,8 @@ fn lint_literal<'tcx>( ty::Float(t) => { let is_infinite = match lit.node { ast::LitKind::Float(v, _) => match t { - ast::FloatTy::F32 => v.as_str().parse().map(f32::is_infinite), - ast::FloatTy::F64 => v.as_str().parse().map(f64::is_infinite), + ty::FloatTy::F32 => v.as_str().parse().map(f32::is_infinite), + ty::FloatTy::F64 => v.as_str().parse().map(f64::is_infinite), }, _ => bug!(), }; @@ -984,7 +998,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { help: Some("consider using `u32` or `libc::wchar_t` instead".into()), }, - ty::Int(ast::IntTy::I128) | ty::Uint(ast::UintTy::U128) => FfiUnsafe { + ty::Int(ty::IntTy::I128) | ty::Uint(ty::UintTy::U128) => FfiUnsafe { ty, reason: "128-bit integers don't currently have a known stable ABI".into(), help: None, diff --git a/compiler/rustc_middle/src/infer/unify_key.rs b/compiler/rustc_middle/src/infer/unify_key.rs index 16e9aafb25a54..8318bdefc8e18 100644 --- a/compiler/rustc_middle/src/infer/unify_key.rs +++ b/compiler/rustc_middle/src/infer/unify_key.rs @@ -1,4 +1,4 @@ -use crate::ty::{self, FloatVarValue, InferConst, IntVarValue, Ty, TyCtxt}; +use crate::ty::{self, InferConst, Ty, TyCtxt}; use rustc_data_structures::snapshot_vec; use rustc_data_structures::undo_log::UndoLogs; use rustc_data_structures::unify::{ @@ -15,36 +15,6 @@ pub trait ToType { fn to_type<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx>; } -/// Raw `TyVid` are used as the unification key for `sub_relations`; -/// they carry no values. -impl UnifyKey for ty::TyVid { - type Value = (); - fn index(&self) -> u32 { - self.index - } - fn from_index(i: u32) -> ty::TyVid { - ty::TyVid { index: i } - } - fn tag() -> &'static str { - "TyVid" - } -} - -impl UnifyKey for ty::IntVid { - type Value = Option; - fn index(&self) -> u32 { - self.index - } - fn from_index(i: u32) -> ty::IntVid { - ty::IntVid { index: i } - } - fn tag() -> &'static str { - "IntVid" - } -} - -impl EqUnifyValue for IntVarValue {} - #[derive(PartialEq, Copy, Clone, Debug)] pub struct RegionVidKey { /// The minimum region vid in the unification set. This is needed @@ -80,7 +50,7 @@ impl UnifyKey for ty::RegionVid { } } -impl ToType for IntVarValue { +impl ToType for ty::IntVarValue { fn to_type<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { match *self { ty::IntType(i) => tcx.mk_mach_int(i), @@ -89,24 +59,7 @@ impl ToType for IntVarValue { } } -// Floating point type keys - -impl UnifyKey for ty::FloatVid { - type Value = Option; - fn index(&self) -> u32 { - self.index - } - fn from_index(i: u32) -> ty::FloatVid { - ty::FloatVid { index: i } - } - fn tag() -> &'static str { - "FloatVid" - } -} - -impl EqUnifyValue for FloatVarValue {} - -impl ToType for FloatVarValue { +impl ToType for ty::FloatVarValue { fn to_type<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { tcx.mk_mach_float(self.0) } diff --git a/compiler/rustc_middle/src/ty/cast.rs b/compiler/rustc_middle/src/ty/cast.rs index d737d1ebf56c6..20a6af5f6c13b 100644 --- a/compiler/rustc_middle/src/ty/cast.rs +++ b/compiler/rustc_middle/src/ty/cast.rs @@ -3,13 +3,12 @@ use crate::ty::{self, Ty}; -use rustc_ast as ast; use rustc_macros::HashStable; /// Types that are represented as ints. #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum IntTy { - U(ast::UintTy), + U(ty::UintTy), I, CEnum, Bool, diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 1cbf761e6c738..1255302f74384 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -19,10 +19,10 @@ use crate::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst, Substs use crate::ty::TyKind::*; use crate::ty::{ self, AdtDef, AdtKind, Binder, BindingMode, BoundVar, CanonicalPolyFnSig, Const, ConstVid, - DefIdTree, ExistentialPredicate, FloatVar, FloatVid, GenericParamDefKind, InferConst, InferTy, - IntVar, IntVid, List, ParamConst, ParamTy, PolyFnSig, Predicate, PredicateInner, PredicateKind, - ProjectionTy, Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyS, TyVar, - TyVid, TypeAndMut, Visibility, + DefIdTree, ExistentialPredicate, FloatTy, FloatVar, FloatVid, GenericParamDefKind, InferConst, + InferTy, IntTy, IntVar, IntVid, List, ParamConst, ParamTy, PolyFnSig, Predicate, + PredicateInner, PredicateKind, ProjectionTy, Region, RegionKind, ReprOptions, + TraitObjectVisitor, Ty, TyKind, TyS, TyVar, TyVid, TypeAndMut, UintTy, Visibility, }; use rustc_ast as ast; use rustc_ast::expand::allocator::AllocatorKind; @@ -839,20 +839,20 @@ impl<'tcx> CommonTypes<'tcx> { bool: mk(Bool), char: mk(Char), never: mk(Never), - isize: mk(Int(ast::IntTy::Isize)), - i8: mk(Int(ast::IntTy::I8)), - i16: mk(Int(ast::IntTy::I16)), - i32: mk(Int(ast::IntTy::I32)), - i64: mk(Int(ast::IntTy::I64)), - i128: mk(Int(ast::IntTy::I128)), - usize: mk(Uint(ast::UintTy::Usize)), - u8: mk(Uint(ast::UintTy::U8)), - u16: mk(Uint(ast::UintTy::U16)), - u32: mk(Uint(ast::UintTy::U32)), - u64: mk(Uint(ast::UintTy::U64)), - u128: mk(Uint(ast::UintTy::U128)), - f32: mk(Float(ast::FloatTy::F32)), - f64: mk(Float(ast::FloatTy::F64)), + isize: mk(Int(ty::IntTy::Isize)), + i8: mk(Int(ty::IntTy::I8)), + i16: mk(Int(ty::IntTy::I16)), + i32: mk(Int(ty::IntTy::I32)), + i64: mk(Int(ty::IntTy::I64)), + i128: mk(Int(ty::IntTy::I128)), + usize: mk(Uint(ty::UintTy::Usize)), + u8: mk(Uint(ty::UintTy::U8)), + u16: mk(Uint(ty::UintTy::U16)), + u32: mk(Uint(ty::UintTy::U32)), + u64: mk(Uint(ty::UintTy::U64)), + u128: mk(Uint(ty::UintTy::U128)), + f32: mk(Float(ty::FloatTy::F32)), + f64: mk(Float(ty::FloatTy::F64)), str_: mk(Str), self_param: mk(ty::Param(ty::ParamTy { index: 0, name: kw::SelfUpper })), @@ -2102,32 +2102,32 @@ impl<'tcx> TyCtxt<'tcx> { if pred.kind() != binder { self.mk_predicate(binder) } else { pred } } - pub fn mk_mach_int(self, tm: ast::IntTy) -> Ty<'tcx> { + pub fn mk_mach_int(self, tm: IntTy) -> Ty<'tcx> { match tm { - ast::IntTy::Isize => self.types.isize, - ast::IntTy::I8 => self.types.i8, - ast::IntTy::I16 => self.types.i16, - ast::IntTy::I32 => self.types.i32, - ast::IntTy::I64 => self.types.i64, - ast::IntTy::I128 => self.types.i128, + IntTy::Isize => self.types.isize, + IntTy::I8 => self.types.i8, + IntTy::I16 => self.types.i16, + IntTy::I32 => self.types.i32, + IntTy::I64 => self.types.i64, + IntTy::I128 => self.types.i128, } } - pub fn mk_mach_uint(self, tm: ast::UintTy) -> Ty<'tcx> { + pub fn mk_mach_uint(self, tm: UintTy) -> Ty<'tcx> { match tm { - ast::UintTy::Usize => self.types.usize, - ast::UintTy::U8 => self.types.u8, - ast::UintTy::U16 => self.types.u16, - ast::UintTy::U32 => self.types.u32, - ast::UintTy::U64 => self.types.u64, - ast::UintTy::U128 => self.types.u128, + UintTy::Usize => self.types.usize, + UintTy::U8 => self.types.u8, + UintTy::U16 => self.types.u16, + UintTy::U32 => self.types.u32, + UintTy::U64 => self.types.u64, + UintTy::U128 => self.types.u128, } } - pub fn mk_mach_float(self, tm: ast::FloatTy) -> Ty<'tcx> { + pub fn mk_mach_float(self, tm: FloatTy) -> Ty<'tcx> { match tm { - ast::FloatTy::F32 => self.types.f32, - ast::FloatTy::F64 => self.types.f64, + FloatTy::F32 => self.types.f32, + FloatTy::F64 => self.types.f64, } } diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index 3adcdbe591fc3..e386d973ee447 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -1,8 +1,7 @@ //! Diagnostics related methods for `TyS`. -use crate::ty::sty::InferTy; use crate::ty::TyKind::*; -use crate::ty::{TyCtxt, TyS}; +use crate::ty::{InferTy, TyCtxt, TyS}; use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::def_id::DefId; diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index f172790fe5fff..c211f07bed8c2 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -1,7 +1,6 @@ use crate::traits::{ObligationCause, ObligationCauseCode}; use crate::ty::diagnostics::suggest_constraining_type_param; use crate::ty::{self, BoundRegionKind, Region, Ty, TyCtxt}; -use rustc_ast as ast; use rustc_errors::Applicability::{MachineApplicable, MaybeIncorrect}; use rustc_errors::{pluralize, DiagnosticBuilder}; use rustc_hir as hir; @@ -48,7 +47,7 @@ pub enum TypeError<'tcx> { Sorts(ExpectedFound>), IntMismatch(ExpectedFound), - FloatMismatch(ExpectedFound), + FloatMismatch(ExpectedFound), Traits(ExpectedFound), VariadicMismatch(ExpectedFound), diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs index 860f91db2bf7a..94d75a469d3d7 100644 --- a/compiler/rustc_middle/src/ty/fast_reject.rs +++ b/compiler/rustc_middle/src/ty/fast_reject.rs @@ -1,6 +1,5 @@ use crate::ich::StableHashingContext; use crate::ty::{self, Ty, TyCtxt}; -use rustc_ast as ast; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_hir::def_id::DefId; use std::fmt::Debug; @@ -24,9 +23,9 @@ where { BoolSimplifiedType, CharSimplifiedType, - IntSimplifiedType(ast::IntTy), - UintSimplifiedType(ast::UintTy), - FloatSimplifiedType(ast::FloatTy), + IntSimplifiedType(ty::IntTy), + UintSimplifiedType(ty::UintTy), + FloatSimplifiedType(ty::FloatTy), AdtSimplifiedType(D), StrSimplifiedType, ArraySimplifiedType, diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index ef467ed651454..ee837d88b7b25 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -4,7 +4,7 @@ use crate::mir::{GeneratorLayout, GeneratorSavedLocal}; use crate::ty::subst::Subst; use crate::ty::{self, subst::SubstsRef, ReprOptions, Ty, TyCtxt, TypeFoldable}; -use rustc_ast::{self as ast, IntTy, UintTy}; +use rustc_ast as ast; use rustc_attr as attr; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_hir as hir; @@ -30,6 +30,8 @@ use std::ops::Bound; pub trait IntegerExt { fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>, signed: bool) -> Ty<'tcx>; fn from_attr(cx: &C, ity: attr::IntType) -> Integer; + fn from_int_ty(cx: &C, ity: ty::IntTy) -> Integer; + fn from_uint_ty(cx: &C, uty: ty::UintTy) -> Integer; fn repr_discr<'tcx>( tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, @@ -60,17 +62,38 @@ impl IntegerExt for Integer { let dl = cx.data_layout(); match ity { - attr::SignedInt(IntTy::I8) | attr::UnsignedInt(UintTy::U8) => I8, - attr::SignedInt(IntTy::I16) | attr::UnsignedInt(UintTy::U16) => I16, - attr::SignedInt(IntTy::I32) | attr::UnsignedInt(UintTy::U32) => I32, - attr::SignedInt(IntTy::I64) | attr::UnsignedInt(UintTy::U64) => I64, - attr::SignedInt(IntTy::I128) | attr::UnsignedInt(UintTy::U128) => I128, - attr::SignedInt(IntTy::Isize) | attr::UnsignedInt(UintTy::Usize) => { + attr::SignedInt(ast::IntTy::I8) | attr::UnsignedInt(ast::UintTy::U8) => I8, + attr::SignedInt(ast::IntTy::I16) | attr::UnsignedInt(ast::UintTy::U16) => I16, + attr::SignedInt(ast::IntTy::I32) | attr::UnsignedInt(ast::UintTy::U32) => I32, + attr::SignedInt(ast::IntTy::I64) | attr::UnsignedInt(ast::UintTy::U64) => I64, + attr::SignedInt(ast::IntTy::I128) | attr::UnsignedInt(ast::UintTy::U128) => I128, + attr::SignedInt(ast::IntTy::Isize) | attr::UnsignedInt(ast::UintTy::Usize) => { dl.ptr_sized_integer() } } } + fn from_int_ty(cx: &C, ity: ty::IntTy) -> Integer { + match ity { + ty::IntTy::I8 => I8, + ty::IntTy::I16 => I16, + ty::IntTy::I32 => I32, + ty::IntTy::I64 => I64, + ty::IntTy::I128 => I128, + ty::IntTy::Isize => cx.data_layout().ptr_sized_integer(), + } + } + fn from_uint_ty(cx: &C, ity: ty::UintTy) -> Integer { + match ity { + ty::UintTy::U8 => I8, + ty::UintTy::U16 => I16, + ty::UintTy::U32 => I32, + ty::UintTy::U64 => I64, + ty::UintTy::U128 => I128, + ty::UintTy::Usize => cx.data_layout().ptr_sized_integer(), + } + } + /// Finds the appropriate Integer type and signedness for the given /// signed discriminant range and `#[repr]` attribute. /// N.B.: `u128` values above `i128::MAX` will be treated as signed, but @@ -487,11 +510,11 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { self, Scalar { value: Int(I32, false), valid_range: 0..=0x10FFFF }, )), - ty::Int(ity) => scalar(Int(Integer::from_attr(dl, attr::SignedInt(ity)), true)), - ty::Uint(ity) => scalar(Int(Integer::from_attr(dl, attr::UnsignedInt(ity)), false)), + ty::Int(ity) => scalar(Int(Integer::from_int_ty(dl, ity), true)), + ty::Uint(ity) => scalar(Int(Integer::from_uint_ty(dl, ity), false)), ty::Float(fty) => scalar(match fty { - ast::FloatTy::F32 => F32, - ast::FloatTy::F64 => F64, + ty::FloatTy::F32 => F32, + ty::FloatTy::F64 => F64, }), ty::FnPtr(_) => { let mut ptr = scalar_unit(Pointer); diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index c4d867161386d..8e8caa46c3802 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -65,7 +65,6 @@ use std::ptr; use std::str; pub use self::sty::BoundRegionKind::*; -pub use self::sty::InferTy::*; pub use self::sty::RegionKind; pub use self::sty::RegionKind::*; pub use self::sty::TyKind::*; @@ -74,13 +73,14 @@ pub use self::sty::{BoundRegion, BoundRegionKind, EarlyBoundRegion, FreeRegion, pub use self::sty::{CanonicalPolyFnSig, FnSig, GenSig, PolyFnSig, PolyGenSig}; pub use self::sty::{ClosureSubsts, GeneratorSubsts, TypeAndMut, UpvarSubsts}; pub use self::sty::{ClosureSubstsParts, GeneratorSubstsParts}; -pub use self::sty::{ConstVid, FloatVid, IntVid, RegionVid, TyVid}; -pub use self::sty::{ExistentialPredicate, InferTy, ParamConst, ParamTy, ProjectionTy}; +pub use self::sty::{ConstVid, RegionVid}; +pub use self::sty::{ExistentialPredicate, ParamConst, ParamTy, ProjectionTy}; pub use self::sty::{ExistentialProjection, PolyExistentialProjection}; pub use self::sty::{ExistentialTraitRef, PolyExistentialTraitRef}; pub use self::sty::{PolyTraitRef, TraitRef, TyKind}; pub use crate::ty::diagnostics::*; -pub use rustc_type_ir::{DebruijnIndex, TypeFlags, INNERMOST}; +pub use rustc_type_ir::InferTy::*; +pub use rustc_type_ir::*; pub use self::binding::BindingMode; pub use self::binding::BindingMode::*; @@ -421,14 +421,6 @@ impl Visibility { } } -#[derive(Copy, Clone, PartialEq, TyDecodable, TyEncodable, HashStable)] -pub enum Variance { - Covariant, // T <: T iff A <: B -- e.g., function return type - Invariant, // T <: T iff B == A -- e.g., type of mutable cell - Contravariant, // T <: T iff B <: A -- e.g., function param type - Bivariant, // T <: T -- e.g., unused type parameter -} - /// The crate variances map is computed during typeck and contains the /// variance of every item in the local crate. You should not use it /// directly, because to do so will make your pass dependent on the @@ -443,66 +435,6 @@ pub struct CrateVariancesMap<'tcx> { pub variances: FxHashMap, } -impl Variance { - /// `a.xform(b)` combines the variance of a context with the - /// variance of a type with the following meaning. If we are in a - /// context with variance `a`, and we encounter a type argument in - /// a position with variance `b`, then `a.xform(b)` is the new - /// variance with which the argument appears. - /// - /// Example 1: - /// - /// *mut Vec - /// - /// Here, the "ambient" variance starts as covariant. `*mut T` is - /// invariant with respect to `T`, so the variance in which the - /// `Vec` appears is `Covariant.xform(Invariant)`, which - /// yields `Invariant`. Now, the type `Vec` is covariant with - /// respect to its type argument `T`, and hence the variance of - /// the `i32` here is `Invariant.xform(Covariant)`, which results - /// (again) in `Invariant`. - /// - /// Example 2: - /// - /// fn(*const Vec, *mut Vec` appears is - /// `Contravariant.xform(Covariant)` or `Contravariant`. The same - /// is true for its `i32` argument. In the `*mut T` case, the - /// variance of `Vec` is `Contravariant.xform(Invariant)`, - /// and hence the outermost type is `Invariant` with respect to - /// `Vec` (and its `i32` argument). - /// - /// Source: Figure 1 of "Taming the Wildcards: - /// Combining Definition- and Use-Site Variance" published in PLDI'11. - pub fn xform(self, v: ty::Variance) -> ty::Variance { - match (self, v) { - // Figure 1, column 1. - (ty::Covariant, ty::Covariant) => ty::Covariant, - (ty::Covariant, ty::Contravariant) => ty::Contravariant, - (ty::Covariant, ty::Invariant) => ty::Invariant, - (ty::Covariant, ty::Bivariant) => ty::Bivariant, - - // Figure 1, column 2. - (ty::Contravariant, ty::Covariant) => ty::Contravariant, - (ty::Contravariant, ty::Contravariant) => ty::Covariant, - (ty::Contravariant, ty::Invariant) => ty::Invariant, - (ty::Contravariant, ty::Bivariant) => ty::Bivariant, - - // Figure 1, column 3. - (ty::Invariant, _) => ty::Invariant, - - // Figure 1, column 4. - (ty::Bivariant, _) => ty::Bivariant, - } - } -} - // Contains information needed to resolve types and (in the future) look up // the types of AST nodes. #[derive(Copy, Clone, PartialEq, Eq, Hash)] @@ -780,8 +712,20 @@ pub fn place_to_string_for_capture(tcx: TyCtxt<'tcx>, place: &HirPlace<'tcx>) -> pub struct CaptureInfo<'tcx> { /// Expr Id pointing to use that resulted in selecting the current capture kind /// + /// Eg: + /// ```rust,no_run + /// let mut t = (0,1); + /// + /// let c = || { + /// println!("{}",t); // L1 + /// t.1 = 4; // L2 + /// }; + /// ``` + /// `capture_kind_expr_id` will point to the use on L2 and `path_expr_id` will point to the + /// use on L1. + /// /// If the user doesn't enable feature `capture_disjoint_fields` (RFC 2229) then, it is - /// possible that we don't see the use of a particular place resulting in expr_id being + /// possible that we don't see the use of a particular place resulting in capture_kind_expr_id being /// None. In such case we fallback on uvpars_mentioned for span. /// /// Eg: @@ -795,7 +739,12 @@ pub struct CaptureInfo<'tcx> { /// /// In this example, if `capture_disjoint_fields` is **not** set, then x will be captured, /// but we won't see it being used during capture analysis, since it's essentially a discard. - pub expr_id: Option, + pub capture_kind_expr_id: Option, + /// Expr Id pointing to use that resulted the corresponding place being captured + /// + /// See `capture_kind_expr_id` for example. + /// + pub path_expr_id: Option, /// Capture mode that was selected pub capture_kind: UpvarCapture<'tcx>, @@ -804,15 +753,6 @@ pub struct CaptureInfo<'tcx> { pub type UpvarListMap = FxHashMap>; pub type UpvarCaptureMap<'tcx> = FxHashMap>; -#[derive(Clone, Copy, PartialEq, Eq)] -pub enum IntVarValue { - IntType(ast::IntTy), - UintType(ast::UintTy), -} - -#[derive(Clone, Copy, PartialEq, Eq)] -pub struct FloatVarValue(pub ast::FloatTy); - impl ty::EarlyBoundRegion { /// Does this early bound region have a name? Early bound regions normally /// always have names except when using anonymous lifetimes (`'_`). @@ -3122,6 +3062,57 @@ pub fn is_impl_trait_defn(tcx: TyCtxt<'_>, def_id: DefId) -> Option { None } +pub fn int_ty(ity: ast::IntTy) -> IntTy { + match ity { + ast::IntTy::Isize => IntTy::Isize, + ast::IntTy::I8 => IntTy::I8, + ast::IntTy::I16 => IntTy::I16, + ast::IntTy::I32 => IntTy::I32, + ast::IntTy::I64 => IntTy::I64, + ast::IntTy::I128 => IntTy::I128, + } +} + +pub fn uint_ty(uty: ast::UintTy) -> UintTy { + match uty { + ast::UintTy::Usize => UintTy::Usize, + ast::UintTy::U8 => UintTy::U8, + ast::UintTy::U16 => UintTy::U16, + ast::UintTy::U32 => UintTy::U32, + ast::UintTy::U64 => UintTy::U64, + ast::UintTy::U128 => UintTy::U128, + } +} + +pub fn float_ty(fty: ast::FloatTy) -> FloatTy { + match fty { + ast::FloatTy::F32 => FloatTy::F32, + ast::FloatTy::F64 => FloatTy::F64, + } +} + +pub fn ast_int_ty(ity: IntTy) -> ast::IntTy { + match ity { + IntTy::Isize => ast::IntTy::Isize, + IntTy::I8 => ast::IntTy::I8, + IntTy::I16 => ast::IntTy::I16, + IntTy::I32 => ast::IntTy::I32, + IntTy::I64 => ast::IntTy::I64, + IntTy::I128 => ast::IntTy::I128, + } +} + +pub fn ast_uint_ty(uty: UintTy) -> ast::UintTy { + match uty { + UintTy::Usize => ast::UintTy::Usize, + UintTy::U8 => ast::UintTy::U8, + UintTy::U16 => ast::UintTy::U16, + UintTy::U32 => ast::UintTy::U32, + UintTy::U64 => ast::UintTy::U64, + UintTy::U128 => ast::UintTy::U128, + } +} + pub fn provide(providers: &mut ty::query::Providers) { context::provide(providers); erase_regions::provide(providers); diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 8911de41c6d8e..4937fdd73144d 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -3,7 +3,6 @@ use crate::mir::interpret::{AllocId, ConstValue, GlobalAlloc, Pointer, Scalar}; use crate::ty::subst::{GenericArg, GenericArgKind, Subst}; use crate::ty::{self, ConstInt, DefIdTree, ParamConst, ScalarInt, Ty, TyCtxt, TypeFoldable}; use rustc_apfloat::ieee::{Double, Single}; -use rustc_ast as ast; use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; use rustc_hir::def::{self, CtorKind, DefKind, Namespace}; @@ -557,14 +556,19 @@ pub trait PrettyPrinter<'tcx>: } ty::FnPtr(ref bare_fn) => p!(print(bare_fn)), ty::Infer(infer_ty) => { + let verbose = self.tcx().sess.verbose(); if let ty::TyVar(ty_vid) = infer_ty { if let Some(name) = self.infer_ty_name(ty_vid) { p!(write("{}", name)) } else { - p!(write("{}", infer_ty)) + if verbose { + p!(write("{:?}", infer_ty)) + } else { + p!(write("{}", infer_ty)) + } } } else { - p!(write("{}", infer_ty)) + if verbose { p!(write("{:?}", infer_ty)) } else { p!(write("{}", infer_ty)) } } } ty::Error(_) => p!("[type error]"), @@ -968,7 +972,7 @@ pub trait PrettyPrinter<'tcx>: ty::TyS { kind: ty::Array( - ty::TyS { kind: ty::Uint(ast::UintTy::U8), .. }, + ty::TyS { kind: ty::Uint(ty::UintTy::U8), .. }, ty::Const { val: ty::ConstKind::Value(ConstValue::Scalar(int)), .. @@ -997,10 +1001,10 @@ pub trait PrettyPrinter<'tcx>: (Scalar::Int(int), ty::Bool) if int == ScalarInt::FALSE => p!("false"), (Scalar::Int(int), ty::Bool) if int == ScalarInt::TRUE => p!("true"), // Float - (Scalar::Int(int), ty::Float(ast::FloatTy::F32)) => { + (Scalar::Int(int), ty::Float(ty::FloatTy::F32)) => { p!(write("{}f32", Single::try_from(int).unwrap())) } - (Scalar::Int(int), ty::Float(ast::FloatTy::F64)) => { + (Scalar::Int(int), ty::Float(ty::FloatTy::F64)) => { p!(write("{}f64", Double::try_from(int).unwrap())) } // Int @@ -1246,7 +1250,7 @@ pub struct FmtPrinterData<'a, 'tcx, F> { pub region_highlight_mode: RegionHighlightMode, - pub name_resolver: Option Option>>, + pub name_resolver: Option Option>>, } impl Deref for FmtPrinter<'a, 'tcx, F> { @@ -2007,21 +2011,6 @@ define_print_and_forward_display! { p!("fn", pretty_fn_sig(self.inputs(), self.c_variadic, self.output())); } - ty::InferTy { - if cx.tcx().sess.verbose() { - p!(write("{:?}", self)); - return Ok(cx); - } - match *self { - ty::TyVar(_) => p!("_"), - ty::IntVar(_) => p!(write("{}", "{integer}")), - ty::FloatVar(_) => p!(write("{}", "{float}")), - ty::FreshTy(v) => p!(write("FreshTy({})", v)), - ty::FreshIntTy(v) => p!(write("FreshIntTy({})", v)), - ty::FreshFloatTy(v) => p!(write("FreshFloatTy({})", v)) - } - } - ty::TraitRef<'tcx> { p!(write("<{} as {}>", self.self_ty(), self.print_only_trait_path())) } diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index 293b3c6b0470a..af7fc42971954 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -33,15 +33,6 @@ pub trait TypeRelation<'tcx>: Sized { /// relation. Just affects error messages. fn a_is_expected(&self) -> bool; - /// Whether we should look into the substs of unevaluated constants - /// even if `feature(const_evaluatable_checked)` is active. - /// - /// This is needed in `combine` to prevent accidentially creating - /// infinite types as we abuse `TypeRelation` to walk a type there. - fn visit_ct_substs(&self) -> bool { - false - } - fn with_cause(&mut self, _cause: Cause, f: F) -> R where F: FnOnce(&mut Self) -> R, @@ -588,7 +579,7 @@ pub fn super_relate_consts>( ( ty::ConstKind::Unevaluated(a_def, a_substs, None), ty::ConstKind::Unevaluated(b_def, b_substs, None), - ) if tcx.features().const_evaluatable_checked && !relation.visit_ct_substs() => { + ) if tcx.features().const_evaluatable_checked => { if tcx.try_unify_abstract_consts(((a_def, a_substs), (b_def, b_substs))) { Ok(a.val) } else { diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 44c173e356dfb..0ca94a9f1805d 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -111,81 +111,24 @@ impl fmt::Debug for ty::FreeRegion { } } -impl fmt::Debug for ty::Variance { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(match *self { - ty::Covariant => "+", - ty::Contravariant => "-", - ty::Invariant => "o", - ty::Bivariant => "*", - }) - } -} - impl fmt::Debug for ty::FnSig<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "({:?}; c_variadic: {})->{:?}", self.inputs(), self.c_variadic, self.output()) } } -impl fmt::Debug for ty::TyVid { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "_#{}t", self.index) - } -} - impl<'tcx> fmt::Debug for ty::ConstVid<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "_#{}c", self.index) } } -impl fmt::Debug for ty::IntVid { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "_#{}i", self.index) - } -} - -impl fmt::Debug for ty::FloatVid { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "_#{}f", self.index) - } -} - impl fmt::Debug for ty::RegionVid { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "'_#{}r", self.index()) } } -impl fmt::Debug for ty::InferTy { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match *self { - ty::TyVar(ref v) => v.fmt(f), - ty::IntVar(ref v) => v.fmt(f), - ty::FloatVar(ref v) => v.fmt(f), - ty::FreshTy(v) => write!(f, "FreshTy({:?})", v), - ty::FreshIntTy(v) => write!(f, "FreshIntTy({:?})", v), - ty::FreshFloatTy(v) => write!(f, "FreshFloatTy({:?})", v), - } - } -} - -impl fmt::Debug for ty::IntVarValue { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match *self { - ty::IntType(ref v) => v.fmt(f), - ty::UintType(ref v) => v.fmt(f), - } - } -} - -impl fmt::Debug for ty::FloatVarValue { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.0.fmt(f) - } -} - impl fmt::Debug for ty::TraitRef<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { with_no_trimmed_paths(|| fmt::Display::fmt(self, f)) @@ -274,7 +217,7 @@ TrivialTypeFoldableAndLiftImpls! { u64, String, crate::middle::region::Scope, - ::rustc_ast::FloatTy, + crate::ty::FloatTy, ::rustc_ast::InlineAsmOptions, ::rustc_ast::InlineAsmTemplatePiece, ::rustc_ast::NodeId, diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index e53977b5eb978..9cec0eb5be3c5 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -2,17 +2,16 @@ #![allow(rustc::usage_of_ty_tykind)] -use self::InferTy::*; use self::TyKind::*; use crate::infer::canonical::Canonical; use crate::ty::subst::{GenericArg, InternalSubsts, Subst, SubstsRef}; +use crate::ty::InferTy::{self, *}; use crate::ty::{ self, AdtDef, DefIdTree, Discr, Ty, TyCtxt, TypeFlags, TypeFoldable, WithConstness, }; use crate::ty::{DelaySpanBugEmitted, List, ParamEnv, TyS}; use polonius_engine::Atom; -use rustc_ast as ast; use rustc_data_structures::captures::Captures; use rustc_hir as hir; use rustc_hir::def_id::DefId; @@ -104,13 +103,13 @@ pub enum TyKind<'tcx> { Char, /// A primitive signed integer type. For example, `i32`. - Int(ast::IntTy), + Int(ty::IntTy), /// A primitive unsigned integer type. For example, `u32`. - Uint(ast::UintTy), + Uint(ty::UintTy), /// A primitive floating-point type. For example, `f64`. - Float(ast::FloatTy), + Float(ty::FloatTy), /// Algebraic data types (ADT). For example: structures, enumerations and unions. /// @@ -1426,12 +1425,6 @@ pub struct EarlyBoundRegion { pub name: Symbol, } -/// A **ty**pe **v**ariable **ID**. -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)] -pub struct TyVid { - pub index: u32, -} - /// A **`const`** **v**ariable **ID**. #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)] pub struct ConstVid<'tcx> { @@ -1439,18 +1432,6 @@ pub struct ConstVid<'tcx> { pub phantom: PhantomData<&'tcx ()>, } -/// An **int**egral (`u32`, `i32`, `usize`, etc.) type **v**ariable **ID**. -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)] -pub struct IntVid { - pub index: u32, -} - -/// An **float**ing-point (`f32` or `f64`) type **v**ariable **ID**. -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)] -pub struct FloatVid { - pub index: u32, -} - rustc_index::newtype_index! { /// A **region** (lifetime) **v**ariable **ID**. pub struct RegionVid { @@ -1464,43 +1445,6 @@ impl Atom for RegionVid { } } -/// A placeholder for a type that hasn't been inferred yet. -/// -/// E.g., if we have an empty array (`[]`), then we create a fresh -/// type variable for the element type since we won't know until it's -/// used what the element type is supposed to be. -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)] -#[derive(HashStable)] -pub enum InferTy { - /// A type variable. - TyVar(TyVid), - /// An integral type variable (`{integer}`). - /// - /// These are created when the compiler sees an integer literal like - /// `1` that could be several different types (`u8`, `i32`, `u32`, etc.). - /// We don't know until it's used what type it's supposed to be, so - /// we create a fresh type variable. - IntVar(IntVid), - /// A floating-point type variable (`{float}`). - /// - /// These are created when the compiler sees an float literal like - /// `1.0` that could be either an `f32` or an `f64`. - /// We don't know until it's used what type it's supposed to be, so - /// we create a fresh type variable. - FloatVar(FloatVid), - - /// A [`FreshTy`][Self::FreshTy] is one that is generated as a replacement - /// for an unbound type variable. This is convenient for caching etc. See - /// `rustc_infer::infer::freshen` for more details. - /// - /// Compare with [`TyVar`][Self::TyVar]. - FreshTy(u32), - /// Like [`FreshTy`][Self::FreshTy], but as a replacement for [`IntVar`][Self::IntVar]. - FreshIntTy(u32), - /// Like [`FreshTy`][Self::FreshTy], but as a replacement for [`FloatVar`][Self::FloatVar]. - FreshFloatTy(u32), -} - rustc_index::newtype_index! { pub struct BoundVar { .. } } @@ -1853,7 +1797,7 @@ impl<'tcx> TyS<'tcx> { pub fn sequence_element_type(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { match self.kind() { Array(ty, _) | Slice(ty) => ty, - Str => tcx.mk_mach_uint(ast::UintTy::U8), + Str => tcx.mk_mach_uint(ty::UintTy::U8), _ => bug!("`sequence_element_type` called on non-sequence value: {}", self), } } @@ -1993,7 +1937,7 @@ impl<'tcx> TyS<'tcx> { #[inline] pub fn is_ptr_sized_integral(&self) -> bool { - matches!(self.kind(), Int(ast::IntTy::Isize) | Uint(ast::UintTy::Usize)) + matches!(self.kind(), Int(ty::IntTy::Isize) | Uint(ty::UintTy::Usize)) } #[inline] @@ -2181,9 +2125,9 @@ impl<'tcx> TyS<'tcx> { pub fn to_opt_closure_kind(&self) -> Option { match self.kind() { Int(int_ty) => match int_ty { - ast::IntTy::I8 => Some(ty::ClosureKind::Fn), - ast::IntTy::I16 => Some(ty::ClosureKind::FnMut), - ast::IntTy::I32 => Some(ty::ClosureKind::FnOnce), + ty::IntTy::I8 => Some(ty::ClosureKind::Fn), + ty::IntTy::I16 => Some(ty::ClosureKind::FnMut), + ty::IntTy::I32 => Some(ty::ClosureKind::FnOnce), _ => bug!("cannot convert type `{:?}` to a closure kind", self), }, diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index a64580336ad62..8edde8794ed27 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -34,7 +34,7 @@ impl<'tcx> fmt::Display for Discr<'tcx> { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { match *self.ty.kind() { ty::Int(ity) => { - let size = ty::tls::with(|tcx| Integer::from_attr(&tcx, SignedInt(ity)).size()); + let size = ty::tls::with(|tcx| Integer::from_int_ty(&tcx, ity).size()); let x = self.val; // sign extend the raw representation to be an i128 let x = size.sign_extend(x) as i128; @@ -59,8 +59,8 @@ fn unsigned_max(size: Size) -> u128 { fn int_size_and_signed<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> (Size, bool) { let (int, signed) = match *ty.kind() { - Int(ity) => (Integer::from_attr(&tcx, SignedInt(ity)), true), - Uint(uty) => (Integer::from_attr(&tcx, UnsignedInt(uty)), false), + Int(ity) => (Integer::from_int_ty(&tcx, ity), true), + Uint(uty) => (Integer::from_uint_ty(&tcx, uty), false), _ => bug!("non integer discriminant"), }; (int.size(), signed) @@ -642,8 +642,8 @@ impl<'tcx> ty::TyS<'tcx> { } ty::Char => Some(std::char::MAX as u128), ty::Float(fty) => Some(match fty { - ast::FloatTy::F32 => rustc_apfloat::ieee::Single::INFINITY.to_bits(), - ast::FloatTy::F64 => rustc_apfloat::ieee::Double::INFINITY.to_bits(), + ty::FloatTy::F32 => rustc_apfloat::ieee::Single::INFINITY.to_bits(), + ty::FloatTy::F64 => rustc_apfloat::ieee::Double::INFINITY.to_bits(), }), _ => None, }; @@ -661,8 +661,8 @@ impl<'tcx> ty::TyS<'tcx> { } ty::Char => Some(0), ty::Float(fty) => Some(match fty { - ast::FloatTy::F32 => (-::rustc_apfloat::ieee::Single::INFINITY).to_bits(), - ast::FloatTy::F64 => (-::rustc_apfloat::ieee::Double::INFINITY).to_bits(), + ty::FloatTy::F32 => (-::rustc_apfloat::ieee::Single::INFINITY).to_bits(), + ty::FloatTy::F64 => (-::rustc_apfloat::ieee::Double::INFINITY).to_bits(), }), _ => None, }; diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/mutability_errors.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/mutability_errors.rs index e1af6fc07cf8f..73196c732f5bb 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/mutability_errors.rs +++ b/compiler/rustc_mir/src/borrow_check/diagnostics/mutability_errors.rs @@ -1,9 +1,12 @@ use rustc_hir as hir; use rustc_hir::Node; use rustc_index::vec::Idx; -use rustc_middle::mir::{self, ClearCrossCrate, Local, LocalDecl, LocalInfo, Location}; use rustc_middle::mir::{Mutability, Place, PlaceRef, ProjectionElem}; use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_middle::{ + hir::place::PlaceBase, + mir::{self, ClearCrossCrate, Local, LocalDecl, LocalInfo, Location}, +}; use rustc_span::source_map::DesugaringKind; use rustc_span::symbol::{kw, Symbol}; use rustc_span::Span; @@ -241,6 +244,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { format!("mut {}", self.local_names[local].unwrap()), Applicability::MachineApplicable, ); + let tcx = self.infcx.tcx; + if let ty::Closure(id, _) = the_place_err.ty(self.body, tcx).ty.kind() { + self.show_mutating_upvar(tcx, id, the_place_err, &mut err); + } } // Also suggest adding mut for upvars @@ -271,6 +278,14 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { ); } } + + let tcx = self.infcx.tcx; + if let ty::Ref(_, ty, Mutability::Mut) = the_place_err.ty(self.body, tcx).ty.kind() + { + if let ty::Closure(id, _) = ty.kind() { + self.show_mutating_upvar(tcx, id, the_place_err, &mut err); + } + } } // complete hack to approximate old AST-borrowck @@ -463,6 +478,45 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { err.buffer(&mut self.errors_buffer); } + // point to span of upvar making closure call require mutable borrow + fn show_mutating_upvar( + &self, + tcx: TyCtxt<'_>, + id: &hir::def_id::DefId, + the_place_err: PlaceRef<'tcx>, + err: &mut DiagnosticBuilder<'_>, + ) { + let id = id.expect_local(); + let tables = tcx.typeck(id); + let hir_id = tcx.hir().local_def_id_to_hir_id(id); + let (span, place) = &tables.closure_kind_origins()[hir_id]; + let reason = if let PlaceBase::Upvar(upvar_id) = place.base { + let upvar = ty::place_to_string_for_capture(tcx, place); + match tables.upvar_capture(upvar_id) { + ty::UpvarCapture::ByRef(ty::UpvarBorrow { + kind: ty::BorrowKind::MutBorrow, + .. + }) => { + format!("mutable borrow of `{}`", upvar) + } + ty::UpvarCapture::ByValue(_) => { + format!("possible mutation of `{}`", upvar) + } + _ => bug!("upvar `{}` borrowed, but not mutably", upvar), + } + } else { + bug!("not an upvar") + }; + err.span_label( + *span, + format!( + "calling `{}` requires mutable binding due to {}", + self.describe_place(the_place_err).unwrap(), + reason + ), + ); + } + /// Targeted error when encountering an `FnMut` closure where an `Fn` closure was expected. fn expected_fn_found_fn_mut_call(&self, err: &mut DiagnosticBuilder<'_>, sp: Span, act: &str) { err.span_label(sp, format!("cannot {}", act)); diff --git a/compiler/rustc_mir/src/const_eval/eval_queries.rs b/compiler/rustc_mir/src/const_eval/eval_queries.rs index df163f6562842..252f5e7ef2ff2 100644 --- a/compiler/rustc_mir/src/const_eval/eval_queries.rs +++ b/compiler/rustc_mir/src/const_eval/eval_queries.rs @@ -298,6 +298,8 @@ pub fn eval_to_allocation_raw_provider<'tcx>( tcx.def_span(def.did), key.param_env, CompileTimeInterpreter::new(tcx.sess.const_eval_limit()), + // Statics (and promoteds inside statics) may access other statics, because unlike consts + // they do not have to behave "as if" they were evaluated at runtime. MemoryExtra { can_access_statics: is_static }, ); @@ -305,83 +307,35 @@ pub fn eval_to_allocation_raw_provider<'tcx>( match res.and_then(|body| eval_body_using_ecx(&mut ecx, cid, &body)) { Err(error) => { let err = ConstEvalErr::new(&ecx, error, None); - // errors in statics are always emitted as fatal errors - if is_static { - // Ensure that if the above error was either `TooGeneric` or `Reported` - // an error must be reported. - let v = err.report_as_error( - ecx.tcx.at(ecx.cur_span()), - "could not evaluate static initializer", - ); - - // If this is `Reveal:All`, then we need to make sure an error is reported but if - // this is `Reveal::UserFacing`, then it's expected that we could get a - // `TooGeneric` error. When we fall back to `Reveal::All`, then it will either - // succeed or we'll report this error then. - if key.param_env.reveal() == Reveal::All { - tcx.sess.delay_span_bug( - err.span, - &format!("static eval failure did not emit an error: {:#?}", v), - ); - } - - Err(v) - } else if let Some(def) = def.as_local() { - // constant defined in this crate, we can figure out a lint level! - match tcx.def_kind(def.did.to_def_id()) { - // constants never produce a hard error at the definition site. Anything else is - // a backwards compatibility hazard (and will break old versions of winapi for - // sure) - // - // note that validation may still cause a hard error on this very same constant, - // because any code that existed before validation could not have failed - // validation thus preventing such a hard error from being a backwards - // compatibility hazard - DefKind::Const | DefKind::AssocConst => { - let hir_id = tcx.hir().local_def_id_to_hir_id(def.did); - Err(err.report_as_lint( - tcx.at(tcx.def_span(def.did)), - "any use of this value will cause an error", - hir_id, - Some(err.span), - )) - } - // promoting runtime code is only allowed to error if it references broken - // constants any other kind of error will be reported to the user as a - // deny-by-default lint - _ => { - if let Some(p) = cid.promoted { - let span = tcx.promoted_mir_opt_const_arg(def.to_global())[p].span; - if let err_inval!(ReferencedConstant) = err.error { - Err(err.report_as_error( - tcx.at(span), - "evaluation of constant expression failed", - )) - } else { - Err(err.report_as_lint( - tcx.at(span), - "reaching this expression at runtime will panic or abort", - tcx.hir().local_def_id_to_hir_id(def.did), - Some(err.span), - )) - } - // anything else (array lengths, enum initializers, constant patterns) are - // reported as hard errors - } else { - Err(err.report_as_error( - ecx.tcx.at(ecx.cur_span()), - "evaluation of constant value failed", - )) - } - } - } + // Some CTFE errors raise just a lint, not a hard error; see + // . + let emit_as_lint = if let Some(def) = def.as_local() { + // (Associated) consts only emit a lint, since they might be unused. + matches!(tcx.def_kind(def.did.to_def_id()), DefKind::Const | DefKind::AssocConst) } else { - // use of broken constant from other crate - Err(err.report_as_error(ecx.tcx.at(ecx.cur_span()), "could not evaluate constant")) + // use of broken constant from other crate: always an error + false + }; + if emit_as_lint { + let hir_id = tcx.hir().local_def_id_to_hir_id(def.as_local().unwrap().did); + Err(err.report_as_lint( + tcx.at(tcx.def_span(def.did)), + "any use of this value will cause an error", + hir_id, + Some(err.span), + )) + } else { + let msg = if is_static { + "could not evaluate static initializer" + } else { + "evaluation of constant value failed" + }; + Err(err.report_as_error(ecx.tcx.at(ecx.cur_span()), msg)) } } Ok(mplace) => { - // Since evaluation had no errors, valiate the resulting constant: + // Since evaluation had no errors, validate the resulting constant. + // This is a separate `try` block to provide more targeted error reporting. let validation = try { let mut ref_tracking = RefTracking::new(mplace); let mut inner = false; @@ -399,7 +353,7 @@ pub fn eval_to_allocation_raw_provider<'tcx>( } }; if let Err(error) = validation { - // Validation failed, report an error + // Validation failed, report an error. This is always a hard error. let err = ConstEvalErr::new(&ecx, error, None); Err(err.struct_error( ecx.tcx, diff --git a/compiler/rustc_mir/src/interpret/cast.rs b/compiler/rustc_mir/src/interpret/cast.rs index 6d224bcc50b0f..128d8cff95e6b 100644 --- a/compiler/rustc_mir/src/interpret/cast.rs +++ b/compiler/rustc_mir/src/interpret/cast.rs @@ -2,13 +2,11 @@ use std::convert::TryFrom; use rustc_apfloat::ieee::{Double, Single}; use rustc_apfloat::{Float, FloatConvert}; -use rustc_ast::FloatTy; -use rustc_attr as attr; use rustc_middle::mir::interpret::{InterpResult, PointerArithmetic, Scalar}; use rustc_middle::mir::CastKind; use rustc_middle::ty::adjustment::PointerCast; use rustc_middle::ty::layout::{IntegerExt, TyAndLayout}; -use rustc_middle::ty::{self, Ty, TypeAndMut}; +use rustc_middle::ty::{self, FloatTy, Ty, TypeAndMut}; use rustc_span::symbol::sym; use rustc_target::abi::{Integer, LayoutOf, Variants}; @@ -203,8 +201,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { match *cast_ty.kind() { Int(_) | Uint(_) | RawPtr(_) => { let size = match *cast_ty.kind() { - Int(t) => Integer::from_attr(self, attr::IntType::SignedInt(t)).size(), - Uint(t) => Integer::from_attr(self, attr::IntType::UnsignedInt(t)).size(), + Int(t) => Integer::from_int_ty(self, t).size(), + Uint(t) => Integer::from_uint_ty(self, t).size(), RawPtr(_) => self.pointer_size(), _ => bug!(), }; @@ -235,7 +233,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { match *dest_ty.kind() { // float -> uint Uint(t) => { - let size = Integer::from_attr(self, attr::IntType::UnsignedInt(t)).size(); + let size = Integer::from_uint_ty(self, t).size(); // `to_u128` is a saturating cast, which is what we need // (https://doc.rust-lang.org/nightly/nightly-rustc/rustc_apfloat/trait.Float.html#method.to_i128_r). let v = f.to_u128(size.bits_usize()).value; @@ -244,7 +242,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } // float -> int Int(t) => { - let size = Integer::from_attr(self, attr::IntType::SignedInt(t)).size(); + let size = Integer::from_int_ty(self, t).size(); // `to_i128` is a saturating cast, which is what we need // (https://doc.rust-lang.org/nightly/nightly-rustc/rustc_apfloat/trait.Float.html#method.to_i128_r). let v = f.to_i128(size.bits_usize()).value; diff --git a/compiler/rustc_mir/src/interpret/operand.rs b/compiler/rustc_mir/src/interpret/operand.rs index d9437a312aec0..88236458a213a 100644 --- a/compiler/rustc_mir/src/interpret/operand.rs +++ b/compiler/rustc_mir/src/interpret/operand.rs @@ -511,6 +511,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Constant(ref constant) => { let val = self.subst_from_current_frame_and_normalize_erasing_regions(constant.literal); + // This can still fail: + // * During ConstProp, with `TooGeneric` or since the `requried_consts` were not all + // checked yet. + // * During CTFE, since promoteds in `const`/`static` initializer bodies can fail. self.const_to_op(val, layout)? } }; diff --git a/compiler/rustc_mir/src/interpret/operator.rs b/compiler/rustc_mir/src/interpret/operator.rs index fc266fa74bfa9..f5081655015b4 100644 --- a/compiler/rustc_mir/src/interpret/operator.rs +++ b/compiler/rustc_mir/src/interpret/operator.rs @@ -1,10 +1,9 @@ use std::convert::TryFrom; use rustc_apfloat::Float; -use rustc_ast::FloatTy; use rustc_middle::mir; use rustc_middle::mir::interpret::{InterpResult, Scalar}; -use rustc_middle::ty::{self, layout::TyAndLayout, Ty}; +use rustc_middle::ty::{self, layout::TyAndLayout, FloatTy, Ty}; use rustc_target::abi::LayoutOf; use super::{ImmTy, Immediate, InterpCx, Machine, PlaceTy}; diff --git a/compiler/rustc_mir_build/src/build/matches/simplify.rs b/compiler/rustc_mir_build/src/build/matches/simplify.rs index f30745d71859d..ddfaeafc07cf1 100644 --- a/compiler/rustc_mir_build/src/build/matches/simplify.rs +++ b/compiler/rustc_mir_build/src/build/matches/simplify.rs @@ -15,7 +15,6 @@ use crate::build::matches::{Ascription, Binding, Candidate, MatchPair}; use crate::build::Builder; use crate::thir::{self, *}; -use rustc_attr::{SignedInt, UnsignedInt}; use rustc_hir::RangeEnd; use rustc_middle::mir::Place; use rustc_middle::ty; @@ -203,13 +202,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { (Some(('\u{0000}' as u128, '\u{10FFFF}' as u128, Size::from_bits(32))), 0) } ty::Int(ity) => { - let size = Integer::from_attr(&tcx, SignedInt(ity)).size(); + let size = Integer::from_int_ty(&tcx, ity).size(); let max = size.truncate(u128::MAX); let bias = 1u128 << (size.bits() - 1); (Some((0, max, size)), bias) } ty::Uint(uty) => { - let size = Integer::from_attr(&tcx, UnsignedInt(uty)).size(); + let size = Integer::from_uint_ty(&tcx, uty).size(); let max = size.truncate(u128::MAX); (Some((0, max, size)), 0) } diff --git a/compiler/rustc_mir_build/src/thir/constant.rs b/compiler/rustc_mir_build/src/thir/constant.rs index dfe82317f48c6..969f7d1e3a458 100644 --- a/compiler/rustc_mir_build/src/thir/constant.rs +++ b/compiler/rustc_mir_build/src/thir/constant.rs @@ -39,7 +39,7 @@ crate fn lit_to_const<'tcx>( let id = tcx.allocate_bytes(data); ConstValue::Scalar(Scalar::Ptr(id.into())) } - (ast::LitKind::Byte(n), ty::Uint(ast::UintTy::U8)) => { + (ast::LitKind::Byte(n), ty::Uint(ty::UintTy::U8)) => { ConstValue::Scalar(Scalar::from_uint(*n, Size::from_bytes(1))) } (ast::LitKind::Int(n, _), ty::Uint(_)) | (ast::LitKind::Int(n, _), ty::Int(_)) => { @@ -56,11 +56,11 @@ crate fn lit_to_const<'tcx>( Ok(ty::Const::from_value(tcx, lit, ty)) } -fn parse_float<'tcx>(num: Symbol, fty: ast::FloatTy, neg: bool) -> Result, ()> { +fn parse_float<'tcx>(num: Symbol, fty: ty::FloatTy, neg: bool) -> Result, ()> { let num = num.as_str(); use rustc_apfloat::ieee::{Double, Single}; let scalar = match fty { - ast::FloatTy::F32 => { + ty::FloatTy::F32 => { num.parse::().map_err(|_| ())?; let mut f = num.parse::().unwrap_or_else(|e| { panic!("apfloat::ieee::Single failed to parse `{}`: {:?}", num, e) @@ -70,7 +70,7 @@ fn parse_float<'tcx>(num: Symbol, fty: ast::FloatTy, neg: bool) -> Result { + ty::FloatTy::F64 => { num.parse::().map_err(|_| ())?; let mut f = num.parse::().unwrap_or_else(|e| { panic!("apfloat::ieee::Double failed to parse `{}`: {:?}", num, e) diff --git a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs index db2fa5730a338..e67166c99c8da 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs @@ -52,7 +52,6 @@ use super::{FieldPat, Pat, PatKind, PatRange}; use rustc_data_structures::captures::Captures; use rustc_index::vec::Idx; -use rustc_attr::{SignedInt, UnsignedInt}; use rustc_hir::def_id::DefId; use rustc_hir::{HirId, RangeEnd}; use rustc_middle::mir::interpret::ConstValue; @@ -103,10 +102,10 @@ impl IntRange { ty::Bool => Some((Size::from_bytes(1), 0)), ty::Char => Some((Size::from_bytes(4), 0)), ty::Int(ity) => { - let size = Integer::from_attr(&tcx, SignedInt(ity)).size(); + let size = Integer::from_int_ty(&tcx, ity).size(); Some((size, 1u128 << (size.bits() as u128 - 1))) } - ty::Uint(uty) => Some((Integer::from_attr(&tcx, UnsignedInt(uty)).size(), 0)), + ty::Uint(uty) => Some((Integer::from_uint_ty(&tcx, uty).size(), 0)), _ => None, } } @@ -167,7 +166,7 @@ impl IntRange { fn signed_bias(tcx: TyCtxt<'_>, ty: Ty<'_>) -> u128 { match *ty.kind() { ty::Int(ity) => { - let bits = Integer::from_attr(&tcx, SignedInt(ity)).size().bits() as u128; + let bits = Integer::from_int_ty(&tcx, ity).size().bits() as u128; 1u128 << (bits - 1) } _ => 0, @@ -959,13 +958,13 @@ impl<'tcx> SplitWildcard<'tcx> { smallvec![NonExhaustive] } &ty::Int(ity) => { - let bits = Integer::from_attr(&cx.tcx, SignedInt(ity)).size().bits() as u128; + let bits = Integer::from_int_ty(&cx.tcx, ity).size().bits() as u128; let min = 1u128 << (bits - 1); let max = min - 1; smallvec![make_range(min, max)] } &ty::Uint(uty) => { - let size = Integer::from_attr(&cx.tcx, UnsignedInt(uty)).size(); + let size = Integer::from_uint_ty(&cx.tcx, uty).size(); let max = size.truncate(u128::MAX); smallvec![make_range(0, max)] } diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 7e9a3a37278b7..7186e26be800e 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -9,7 +9,6 @@ pub(crate) use self::check_match::check_match; use crate::thir::util::UserAnnotatedTyHelpers; -use rustc_ast as ast; use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; @@ -1069,20 +1068,19 @@ crate fn compare_const_vals<'tcx>( if let (Some(a), Some(b)) = (a_bits, b_bits) { use rustc_apfloat::Float; return match *ty.kind() { - ty::Float(ast::FloatTy::F32) => { + ty::Float(ty::FloatTy::F32) => { let l = rustc_apfloat::ieee::Single::from_bits(a); let r = rustc_apfloat::ieee::Single::from_bits(b); l.partial_cmp(&r) } - ty::Float(ast::FloatTy::F64) => { + ty::Float(ty::FloatTy::F64) => { let l = rustc_apfloat::ieee::Double::from_bits(a); let r = rustc_apfloat::ieee::Double::from_bits(b); l.partial_cmp(&r) } ty::Int(ity) => { - use rustc_attr::SignedInt; use rustc_middle::ty::layout::IntegerExt; - let size = rustc_target::abi::Integer::from_attr(&tcx, SignedInt(ity)).size(); + let size = rustc_target::abi::Integer::from_int_ty(&tcx, ity).size(); let a = size.sign_extend(a); let b = size.sign_extend(b); Some((a as i128).cmp(&(b as i128))) diff --git a/compiler/rustc_passes/src/intrinsicck.rs b/compiler/rustc_passes/src/intrinsicck.rs index ee90e9c54f69d..0f4bb635eeefd 100644 --- a/compiler/rustc_passes/src/intrinsicck.rs +++ b/compiler/rustc_passes/src/intrinsicck.rs @@ -1,4 +1,4 @@ -use rustc_ast::{FloatTy, InlineAsmTemplatePiece, IntTy, UintTy}; +use rustc_ast::InlineAsmTemplatePiece; use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; @@ -7,7 +7,7 @@ use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_index::vec::Idx; use rustc_middle::ty::layout::{LayoutError, SizeSkeleton}; use rustc_middle::ty::query::Providers; -use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_middle::ty::{self, FloatTy, IntTy, Ty, TyCtxt, UintTy}; use rustc_session::lint; use rustc_span::{sym, Span, Symbol, DUMMY_SP}; use rustc_target::abi::{Pointer, VariantIdx}; diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 7b90e5b611cd1..2e7c9701c0c67 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -622,6 +622,7 @@ symbols! { intel, into_iter, into_result, + into_trait, intra_doc_pointers, intrinsics, irrefutable_let_patterns, @@ -1159,6 +1160,8 @@ symbols! { truncf32, truncf64, try_blocks, + try_from_trait, + try_into_trait, try_trait, tt, tuple, diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 7b6e6ad0696a1..c84e2cb45a6c4 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -1,4 +1,3 @@ -use rustc_ast::{FloatTy, IntTy, UintTy}; use rustc_data_structures::base_n; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir as hir; @@ -6,7 +5,7 @@ use rustc_hir::def_id::{CrateNum, DefId}; use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData}; use rustc_middle::ty::print::{Print, Printer}; use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst}; -use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypeFoldable}; +use rustc_middle::ty::{self, FloatTy, Instance, IntTy, Ty, TyCtxt, TypeFoldable, UintTy}; use rustc_target::spec::abi::Abi; use std::fmt::Write; diff --git a/compiler/rustc_traits/src/chalk/db.rs b/compiler/rustc_traits/src/chalk/db.rs index 1893d74335ab8..bb48ed936188b 100644 --- a/compiler/rustc_traits/src/chalk/db.rs +++ b/compiler/rustc_traits/src/chalk/db.rs @@ -346,26 +346,26 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t (ty::Char, Scalar(Char)) => true, (ty::Int(ty1), Scalar(Int(ty2))) => matches!( (ty1, ty2), - (ast::IntTy::Isize, chalk_ir::IntTy::Isize) - | (ast::IntTy::I8, chalk_ir::IntTy::I8) - | (ast::IntTy::I16, chalk_ir::IntTy::I16) - | (ast::IntTy::I32, chalk_ir::IntTy::I32) - | (ast::IntTy::I64, chalk_ir::IntTy::I64) - | (ast::IntTy::I128, chalk_ir::IntTy::I128) + (ty::IntTy::Isize, chalk_ir::IntTy::Isize) + | (ty::IntTy::I8, chalk_ir::IntTy::I8) + | (ty::IntTy::I16, chalk_ir::IntTy::I16) + | (ty::IntTy::I32, chalk_ir::IntTy::I32) + | (ty::IntTy::I64, chalk_ir::IntTy::I64) + | (ty::IntTy::I128, chalk_ir::IntTy::I128) ), (ty::Uint(ty1), Scalar(Uint(ty2))) => matches!( (ty1, ty2), - (ast::UintTy::Usize, chalk_ir::UintTy::Usize) - | (ast::UintTy::U8, chalk_ir::UintTy::U8) - | (ast::UintTy::U16, chalk_ir::UintTy::U16) - | (ast::UintTy::U32, chalk_ir::UintTy::U32) - | (ast::UintTy::U64, chalk_ir::UintTy::U64) - | (ast::UintTy::U128, chalk_ir::UintTy::U128) + (ty::UintTy::Usize, chalk_ir::UintTy::Usize) + | (ty::UintTy::U8, chalk_ir::UintTy::U8) + | (ty::UintTy::U16, chalk_ir::UintTy::U16) + | (ty::UintTy::U32, chalk_ir::UintTy::U32) + | (ty::UintTy::U64, chalk_ir::UintTy::U64) + | (ty::UintTy::U128, chalk_ir::UintTy::U128) ), (ty::Float(ty1), Scalar(Float(ty2))) => matches!( (ty1, ty2), - (ast::FloatTy::F32, chalk_ir::FloatTy::F32) - | (ast::FloatTy::F64, chalk_ir::FloatTy::F64) + (ty::FloatTy::F32, chalk_ir::FloatTy::F32) + | (ty::FloatTy::F64, chalk_ir::FloatTy::F64) ), (&ty::Tuple(substs), Tuple(len, _)) => substs.len() == *len, (&ty::Array(..), Array(..)) => true, diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs index 48d47054a4182..2a1a3f57e2313 100644 --- a/compiler/rustc_traits/src/chalk/lowering.rs +++ b/compiler/rustc_traits/src/chalk/lowering.rs @@ -233,8 +233,6 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::AliasEq>> impl<'tcx> LowerInto<'tcx, chalk_ir::Ty>> for Ty<'tcx> { fn lower_into(self, interner: &RustInterner<'tcx>) -> chalk_ir::Ty> { - use rustc_ast as ast; - let int = |i| chalk_ir::TyKind::Scalar(chalk_ir::Scalar::Int(i)); let uint = |i| chalk_ir::TyKind::Scalar(chalk_ir::Scalar::Uint(i)); let float = |f| chalk_ir::TyKind::Scalar(chalk_ir::Scalar::Float(f)); @@ -243,24 +241,24 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Ty>> for Ty<'tcx> { ty::Bool => chalk_ir::TyKind::Scalar(chalk_ir::Scalar::Bool), ty::Char => chalk_ir::TyKind::Scalar(chalk_ir::Scalar::Char), ty::Int(ty) => match ty { - ast::IntTy::Isize => int(chalk_ir::IntTy::Isize), - ast::IntTy::I8 => int(chalk_ir::IntTy::I8), - ast::IntTy::I16 => int(chalk_ir::IntTy::I16), - ast::IntTy::I32 => int(chalk_ir::IntTy::I32), - ast::IntTy::I64 => int(chalk_ir::IntTy::I64), - ast::IntTy::I128 => int(chalk_ir::IntTy::I128), + ty::IntTy::Isize => int(chalk_ir::IntTy::Isize), + ty::IntTy::I8 => int(chalk_ir::IntTy::I8), + ty::IntTy::I16 => int(chalk_ir::IntTy::I16), + ty::IntTy::I32 => int(chalk_ir::IntTy::I32), + ty::IntTy::I64 => int(chalk_ir::IntTy::I64), + ty::IntTy::I128 => int(chalk_ir::IntTy::I128), }, ty::Uint(ty) => match ty { - ast::UintTy::Usize => uint(chalk_ir::UintTy::Usize), - ast::UintTy::U8 => uint(chalk_ir::UintTy::U8), - ast::UintTy::U16 => uint(chalk_ir::UintTy::U16), - ast::UintTy::U32 => uint(chalk_ir::UintTy::U32), - ast::UintTy::U64 => uint(chalk_ir::UintTy::U64), - ast::UintTy::U128 => uint(chalk_ir::UintTy::U128), + ty::UintTy::Usize => uint(chalk_ir::UintTy::Usize), + ty::UintTy::U8 => uint(chalk_ir::UintTy::U8), + ty::UintTy::U16 => uint(chalk_ir::UintTy::U16), + ty::UintTy::U32 => uint(chalk_ir::UintTy::U32), + ty::UintTy::U64 => uint(chalk_ir::UintTy::U64), + ty::UintTy::U128 => uint(chalk_ir::UintTy::U128), }, ty::Float(ty) => match ty { - ast::FloatTy::F32 => float(chalk_ir::FloatTy::F32), - ast::FloatTy::F64 => float(chalk_ir::FloatTy::F64), + ty::FloatTy::F32 => float(chalk_ir::FloatTy::F32), + ty::FloatTy::F64 => float(chalk_ir::FloatTy::F64), }, ty::Adt(def, substs) => { chalk_ir::TyKind::Adt(chalk_ir::AdtId(def), substs.lower_into(interner)) @@ -347,24 +345,24 @@ impl<'tcx> LowerInto<'tcx, Ty<'tcx>> for &chalk_ir::Ty> { chalk_ir::Scalar::Bool => ty::Bool, chalk_ir::Scalar::Char => ty::Char, chalk_ir::Scalar::Int(int_ty) => match int_ty { - chalk_ir::IntTy::Isize => ty::Int(ast::IntTy::Isize), - chalk_ir::IntTy::I8 => ty::Int(ast::IntTy::I8), - chalk_ir::IntTy::I16 => ty::Int(ast::IntTy::I16), - chalk_ir::IntTy::I32 => ty::Int(ast::IntTy::I32), - chalk_ir::IntTy::I64 => ty::Int(ast::IntTy::I64), - chalk_ir::IntTy::I128 => ty::Int(ast::IntTy::I128), + chalk_ir::IntTy::Isize => ty::Int(ty::IntTy::Isize), + chalk_ir::IntTy::I8 => ty::Int(ty::IntTy::I8), + chalk_ir::IntTy::I16 => ty::Int(ty::IntTy::I16), + chalk_ir::IntTy::I32 => ty::Int(ty::IntTy::I32), + chalk_ir::IntTy::I64 => ty::Int(ty::IntTy::I64), + chalk_ir::IntTy::I128 => ty::Int(ty::IntTy::I128), }, chalk_ir::Scalar::Uint(int_ty) => match int_ty { - chalk_ir::UintTy::Usize => ty::Uint(ast::UintTy::Usize), - chalk_ir::UintTy::U8 => ty::Uint(ast::UintTy::U8), - chalk_ir::UintTy::U16 => ty::Uint(ast::UintTy::U16), - chalk_ir::UintTy::U32 => ty::Uint(ast::UintTy::U32), - chalk_ir::UintTy::U64 => ty::Uint(ast::UintTy::U64), - chalk_ir::UintTy::U128 => ty::Uint(ast::UintTy::U128), + chalk_ir::UintTy::Usize => ty::Uint(ty::UintTy::Usize), + chalk_ir::UintTy::U8 => ty::Uint(ty::UintTy::U8), + chalk_ir::UintTy::U16 => ty::Uint(ty::UintTy::U16), + chalk_ir::UintTy::U32 => ty::Uint(ty::UintTy::U32), + chalk_ir::UintTy::U64 => ty::Uint(ty::UintTy::U64), + chalk_ir::UintTy::U128 => ty::Uint(ty::UintTy::U128), }, chalk_ir::Scalar::Float(float_ty) => match float_ty { - chalk_ir::FloatTy::F32 => ty::Float(ast::FloatTy::F32), - chalk_ir::FloatTy::F64 => ty::Float(ast::FloatTy::F64), + chalk_ir::FloatTy::F32 => ty::Float(ty::FloatTy::F32), + chalk_ir::FloatTy::F64 => ty::Float(ty::FloatTy::F64), }, }, TyKind::Array(ty, c) => { diff --git a/compiler/rustc_type_ir/Cargo.toml b/compiler/rustc_type_ir/Cargo.toml index d50451b7794c6..3f64bd899979f 100644 --- a/compiler/rustc_type_ir/Cargo.toml +++ b/compiler/rustc_type_ir/Cargo.toml @@ -12,3 +12,4 @@ bitflags = "1.2.1" rustc_index = { path = "../rustc_index" } rustc_serialize = { path = "../rustc_serialize" } rustc_data_structures = { path = "../rustc_data_structures" } +rustc_macros = { path = "../rustc_macros" } diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index 37abb4496ac3f..7e70af21c03cd 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -4,8 +4,13 @@ #[macro_use] extern crate bitflags; +#[macro_use] +extern crate rustc_macros; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_data_structures::unify::{EqUnifyValue, UnifyKey}; +use std::fmt; +use std::mem::discriminant; bitflags! { /// Flags that we track on types. These flags are propagated upwards @@ -197,8 +202,409 @@ impl DebruijnIndex { } } +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] +#[derive(Encodable, Decodable)] +pub enum IntTy { + Isize, + I8, + I16, + I32, + I64, + I128, +} + +impl IntTy { + pub fn name_str(&self) -> &'static str { + match *self { + IntTy::Isize => "isize", + IntTy::I8 => "i8", + IntTy::I16 => "i16", + IntTy::I32 => "i32", + IntTy::I64 => "i64", + IntTy::I128 => "i128", + } + } + + pub fn bit_width(&self) -> Option { + Some(match *self { + IntTy::Isize => return None, + IntTy::I8 => 8, + IntTy::I16 => 16, + IntTy::I32 => 32, + IntTy::I64 => 64, + IntTy::I128 => 128, + }) + } + + pub fn normalize(&self, target_width: u32) -> Self { + match self { + IntTy::Isize => match target_width { + 16 => IntTy::I16, + 32 => IntTy::I32, + 64 => IntTy::I64, + _ => unreachable!(), + }, + _ => *self, + } + } +} + +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, Debug)] +#[derive(Encodable, Decodable)] +pub enum UintTy { + Usize, + U8, + U16, + U32, + U64, + U128, +} + +impl UintTy { + pub fn name_str(&self) -> &'static str { + match *self { + UintTy::Usize => "usize", + UintTy::U8 => "u8", + UintTy::U16 => "u16", + UintTy::U32 => "u32", + UintTy::U64 => "u64", + UintTy::U128 => "u128", + } + } + + pub fn bit_width(&self) -> Option { + Some(match *self { + UintTy::Usize => return None, + UintTy::U8 => 8, + UintTy::U16 => 16, + UintTy::U32 => 32, + UintTy::U64 => 64, + UintTy::U128 => 128, + }) + } + + pub fn normalize(&self, target_width: u32) -> Self { + match self { + UintTy::Usize => match target_width { + 16 => UintTy::U16, + 32 => UintTy::U32, + 64 => UintTy::U64, + _ => unreachable!(), + }, + _ => *self, + } + } +} + +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] +#[derive(Encodable, Decodable)] +pub enum FloatTy { + F32, + F64, +} + +impl FloatTy { + pub fn name_str(self) -> &'static str { + match self { + FloatTy::F32 => "f32", + FloatTy::F64 => "f64", + } + } + + pub fn bit_width(self) -> u64 { + match self { + FloatTy::F32 => 32, + FloatTy::F64 => 64, + } + } +} + +#[derive(Clone, Copy, PartialEq, Eq)] +pub enum IntVarValue { + IntType(IntTy), + UintType(UintTy), +} + +#[derive(Clone, Copy, PartialEq, Eq)] +pub struct FloatVarValue(pub FloatTy); + +/// A **ty**pe **v**ariable **ID**. +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)] +pub struct TyVid { + pub index: u32, +} + +/// An **int**egral (`u32`, `i32`, `usize`, etc.) type **v**ariable **ID**. +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)] +pub struct IntVid { + pub index: u32, +} + +/// An **float**ing-point (`f32` or `f64`) type **v**ariable **ID**. +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)] +pub struct FloatVid { + pub index: u32, +} + +/// A placeholder for a type that hasn't been inferred yet. +/// +/// E.g., if we have an empty array (`[]`), then we create a fresh +/// type variable for the element type since we won't know until it's +/// used what the element type is supposed to be. +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)] +pub enum InferTy { + /// A type variable. + TyVar(TyVid), + /// An integral type variable (`{integer}`). + /// + /// These are created when the compiler sees an integer literal like + /// `1` that could be several different types (`u8`, `i32`, `u32`, etc.). + /// We don't know until it's used what type it's supposed to be, so + /// we create a fresh type variable. + IntVar(IntVid), + /// A floating-point type variable (`{float}`). + /// + /// These are created when the compiler sees an float literal like + /// `1.0` that could be either an `f32` or an `f64`. + /// We don't know until it's used what type it's supposed to be, so + /// we create a fresh type variable. + FloatVar(FloatVid), + + /// A [`FreshTy`][Self::FreshTy] is one that is generated as a replacement + /// for an unbound type variable. This is convenient for caching etc. See + /// `rustc_infer::infer::freshen` for more details. + /// + /// Compare with [`TyVar`][Self::TyVar]. + FreshTy(u32), + /// Like [`FreshTy`][Self::FreshTy], but as a replacement for [`IntVar`][Self::IntVar]. + FreshIntTy(u32), + /// Like [`FreshTy`][Self::FreshTy], but as a replacement for [`FloatVar`][Self::FloatVar]. + FreshFloatTy(u32), +} + +/// Raw `TyVid` are used as the unification key for `sub_relations`; +/// they carry no values. +impl UnifyKey for TyVid { + type Value = (); + fn index(&self) -> u32 { + self.index + } + fn from_index(i: u32) -> TyVid { + TyVid { index: i } + } + fn tag() -> &'static str { + "TyVid" + } +} + +impl EqUnifyValue for IntVarValue {} + +impl UnifyKey for IntVid { + type Value = Option; + fn index(&self) -> u32 { + self.index + } + fn from_index(i: u32) -> IntVid { + IntVid { index: i } + } + fn tag() -> &'static str { + "IntVid" + } +} + +impl EqUnifyValue for FloatVarValue {} + +impl UnifyKey for FloatVid { + type Value = Option; + fn index(&self) -> u32 { + self.index + } + fn from_index(i: u32) -> FloatVid { + FloatVid { index: i } + } + fn tag() -> &'static str { + "FloatVid" + } +} + +#[derive(Copy, Clone, PartialEq, Decodable, Encodable)] +pub enum Variance { + Covariant, // T <: T iff A <: B -- e.g., function return type + Invariant, // T <: T iff B == A -- e.g., type of mutable cell + Contravariant, // T <: T iff B <: A -- e.g., function param type + Bivariant, // T <: T -- e.g., unused type parameter +} + +impl Variance { + /// `a.xform(b)` combines the variance of a context with the + /// variance of a type with the following meaning. If we are in a + /// context with variance `a`, and we encounter a type argument in + /// a position with variance `b`, then `a.xform(b)` is the new + /// variance with which the argument appears. + /// + /// Example 1: + /// + /// *mut Vec + /// + /// Here, the "ambient" variance starts as covariant. `*mut T` is + /// invariant with respect to `T`, so the variance in which the + /// `Vec` appears is `Covariant.xform(Invariant)`, which + /// yields `Invariant`. Now, the type `Vec` is covariant with + /// respect to its type argument `T`, and hence the variance of + /// the `i32` here is `Invariant.xform(Covariant)`, which results + /// (again) in `Invariant`. + /// + /// Example 2: + /// + /// fn(*const Vec, *mut Vec` appears is + /// `Contravariant.xform(Covariant)` or `Contravariant`. The same + /// is true for its `i32` argument. In the `*mut T` case, the + /// variance of `Vec` is `Contravariant.xform(Invariant)`, + /// and hence the outermost type is `Invariant` with respect to + /// `Vec` (and its `i32` argument). + /// + /// Source: Figure 1 of "Taming the Wildcards: + /// Combining Definition- and Use-Site Variance" published in PLDI'11. + pub fn xform(self, v: Variance) -> Variance { + match (self, v) { + // Figure 1, column 1. + (Variance::Covariant, Variance::Covariant) => Variance::Covariant, + (Variance::Covariant, Variance::Contravariant) => Variance::Contravariant, + (Variance::Covariant, Variance::Invariant) => Variance::Invariant, + (Variance::Covariant, Variance::Bivariant) => Variance::Bivariant, + + // Figure 1, column 2. + (Variance::Contravariant, Variance::Covariant) => Variance::Contravariant, + (Variance::Contravariant, Variance::Contravariant) => Variance::Covariant, + (Variance::Contravariant, Variance::Invariant) => Variance::Invariant, + (Variance::Contravariant, Variance::Bivariant) => Variance::Bivariant, + + // Figure 1, column 3. + (Variance::Invariant, _) => Variance::Invariant, + + // Figure 1, column 4. + (Variance::Bivariant, _) => Variance::Bivariant, + } + } +} + impl HashStable for DebruijnIndex { fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { self.as_u32().hash_stable(ctx, hasher); } } + +impl HashStable for IntTy { + fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { + discriminant(self).hash_stable(ctx, hasher); + } +} + +impl HashStable for UintTy { + fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { + discriminant(self).hash_stable(ctx, hasher); + } +} + +impl HashStable for FloatTy { + fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { + discriminant(self).hash_stable(ctx, hasher); + } +} + +impl HashStable for InferTy { + fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { + use InferTy::*; + match self { + TyVar(v) => v.index.hash_stable(ctx, hasher), + IntVar(v) => v.index.hash_stable(ctx, hasher), + FloatVar(v) => v.index.hash_stable(ctx, hasher), + FreshTy(v) | FreshIntTy(v) | FreshFloatTy(v) => v.hash_stable(ctx, hasher), + } + } +} + +impl HashStable for Variance { + fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { + discriminant(self).hash_stable(ctx, hasher); + } +} + +impl fmt::Debug for IntVarValue { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match *self { + IntVarValue::IntType(ref v) => v.fmt(f), + IntVarValue::UintType(ref v) => v.fmt(f), + } + } +} + +impl fmt::Debug for FloatVarValue { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.0.fmt(f) + } +} + +impl fmt::Debug for TyVid { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "_#{}t", self.index) + } +} + +impl fmt::Debug for IntVid { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "_#{}i", self.index) + } +} + +impl fmt::Debug for FloatVid { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "_#{}f", self.index) + } +} + +impl fmt::Debug for InferTy { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + use InferTy::*; + match *self { + TyVar(ref v) => v.fmt(f), + IntVar(ref v) => v.fmt(f), + FloatVar(ref v) => v.fmt(f), + FreshTy(v) => write!(f, "FreshTy({:?})", v), + FreshIntTy(v) => write!(f, "FreshIntTy({:?})", v), + FreshFloatTy(v) => write!(f, "FreshFloatTy({:?})", v), + } + } +} + +impl fmt::Debug for Variance { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(match *self { + Variance::Covariant => "+", + Variance::Contravariant => "-", + Variance::Invariant => "o", + Variance::Bivariant => "*", + }) + } +} + +impl fmt::Display for InferTy { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + use InferTy::*; + match *self { + TyVar(_) => write!(f, "_"), + IntVar(_) => write!(f, "{}", "{integer}"), + FloatVar(_) => write!(f, "{}", "{float}"), + FreshTy(v) => write!(f, "FreshTy({})", v), + FreshIntTy(v) => write!(f, "FreshIntTy({})", v), + FreshFloatTy(v) => write!(f, "FreshFloatTy({})", v), + } + } +} diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 059f9b41068c7..437813ea41bd5 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -2059,9 +2059,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { match prim_ty { hir::PrimTy::Bool => tcx.types.bool, hir::PrimTy::Char => tcx.types.char, - hir::PrimTy::Int(it) => tcx.mk_mach_int(it), - hir::PrimTy::Uint(uit) => tcx.mk_mach_uint(uit), - hir::PrimTy::Float(ft) => tcx.mk_mach_float(ft), + hir::PrimTy::Int(it) => tcx.mk_mach_int(ty::int_ty(it)), + hir::PrimTy::Uint(uit) => tcx.mk_mach_uint(ty::uint_ty(uit)), + hir::PrimTy::Float(ft) => tcx.mk_mach_float(ty::float_ty(ft)), hir::PrimTy::Str => tcx.types.str_, } } diff --git a/compiler/rustc_typeck/src/check/cast.rs b/compiler/rustc_typeck/src/check/cast.rs index 39dac0a909f6f..7924ffe8a6fd5 100644 --- a/compiler/rustc_typeck/src/check/cast.rs +++ b/compiler/rustc_typeck/src/check/cast.rs @@ -32,7 +32,6 @@ use super::FnCtxt; use crate::hir::def_id::DefId; use crate::type_error_struct; -use rustc_ast as ast; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorReported}; use rustc_hir as hir; use rustc_hir::lang_items::LangItem; @@ -660,7 +659,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { (_, Int(Bool)) => Err(CastError::CastToBool), // * -> Char - (Int(U(ast::UintTy::U8)), Int(Char)) => Ok(CastKind::U8CharCast), // u8-char-cast + (Int(U(ty::UintTy::U8)), Int(Char)) => Ok(CastKind::U8CharCast), // u8-char-cast (_, Int(Char)) => Err(CastError::CastToChar), // prim -> float,ptr diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs index fb6f9c03352b4..3326be796cee3 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs @@ -372,13 +372,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // in C but we just error out instead and require explicit casts. let arg_ty = self.structurally_resolved_type(arg.span, arg_ty); match arg_ty.kind() { - ty::Float(ast::FloatTy::F32) => { + ty::Float(ty::FloatTy::F32) => { variadic_error(tcx.sess, arg.span, arg_ty, "c_double"); } - ty::Int(ast::IntTy::I8 | ast::IntTy::I16) | ty::Bool => { + ty::Int(ty::IntTy::I8 | ty::IntTy::I16) | ty::Bool => { variadic_error(tcx.sess, arg.span, arg_ty, "c_int"); } - ty::Uint(ast::UintTy::U8 | ast::UintTy::U16) => { + ty::Uint(ty::UintTy::U8 | ty::UintTy::U16) => { variadic_error(tcx.sess, arg.span, arg_ty, "c_uint"); } ty::FnDef(..) => { @@ -407,8 +407,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } ast::LitKind::Byte(_) => tcx.types.u8, ast::LitKind::Char(_) => tcx.types.char, - ast::LitKind::Int(_, ast::LitIntType::Signed(t)) => tcx.mk_mach_int(t), - ast::LitKind::Int(_, ast::LitIntType::Unsigned(t)) => tcx.mk_mach_uint(t), + ast::LitKind::Int(_, ast::LitIntType::Signed(t)) => tcx.mk_mach_int(ty::int_ty(t)), + ast::LitKind::Int(_, ast::LitIntType::Unsigned(t)) => tcx.mk_mach_uint(ty::uint_ty(t)), ast::LitKind::Int(_, ast::LitIntType::Unsuffixed) => { let opt_ty = expected.to_option(self).and_then(|ty| match ty.kind() { ty::Int(_) | ty::Uint(_) => Some(ty), @@ -419,7 +419,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }); opt_ty.unwrap_or_else(|| self.next_int_var()) } - ast::LitKind::Float(_, ast::LitFloatType::Suffixed(t)) => tcx.mk_mach_float(t), + ast::LitKind::Float(_, ast::LitFloatType::Suffixed(t)) => { + tcx.mk_mach_float(ty::float_ty(t)) + } ast::LitKind::Float(_, ast::LitFloatType::Unsuffixed) => { let opt_ty = expected.to_option(self).and_then(|ty| match ty.kind() { ty::Float(_) => Some(ty), diff --git a/compiler/rustc_typeck/src/check/method/probe.rs b/compiler/rustc_typeck/src/check/method/probe.rs index 8335239f804b0..158c214759db2 100644 --- a/compiler/rustc_typeck/src/check/method/probe.rs +++ b/compiler/rustc_typeck/src/check/method/probe.rs @@ -8,7 +8,6 @@ use crate::errors::MethodCallOnUnknownType; use crate::hir::def::DefKind; use crate::hir::def_id::DefId; -use rustc_ast as ast; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::sync::Lrc; use rustc_hir as hir; @@ -662,30 +661,30 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } ty::Int(i) => { let lang_def_id = match i { - ast::IntTy::I8 => lang_items.i8_impl(), - ast::IntTy::I16 => lang_items.i16_impl(), - ast::IntTy::I32 => lang_items.i32_impl(), - ast::IntTy::I64 => lang_items.i64_impl(), - ast::IntTy::I128 => lang_items.i128_impl(), - ast::IntTy::Isize => lang_items.isize_impl(), + ty::IntTy::I8 => lang_items.i8_impl(), + ty::IntTy::I16 => lang_items.i16_impl(), + ty::IntTy::I32 => lang_items.i32_impl(), + ty::IntTy::I64 => lang_items.i64_impl(), + ty::IntTy::I128 => lang_items.i128_impl(), + ty::IntTy::Isize => lang_items.isize_impl(), }; self.assemble_inherent_impl_for_primitive(lang_def_id); } ty::Uint(i) => { let lang_def_id = match i { - ast::UintTy::U8 => lang_items.u8_impl(), - ast::UintTy::U16 => lang_items.u16_impl(), - ast::UintTy::U32 => lang_items.u32_impl(), - ast::UintTy::U64 => lang_items.u64_impl(), - ast::UintTy::U128 => lang_items.u128_impl(), - ast::UintTy::Usize => lang_items.usize_impl(), + ty::UintTy::U8 => lang_items.u8_impl(), + ty::UintTy::U16 => lang_items.u16_impl(), + ty::UintTy::U32 => lang_items.u32_impl(), + ty::UintTy::U64 => lang_items.u64_impl(), + ty::UintTy::U128 => lang_items.u128_impl(), + ty::UintTy::Usize => lang_items.usize_impl(), }; self.assemble_inherent_impl_for_primitive(lang_def_id); } ty::Float(f) => { let (lang_def_id1, lang_def_id2) = match f { - ast::FloatTy::F32 => (lang_items.f32_impl(), lang_items.f32_runtime_impl()), - ast::FloatTy::F64 => (lang_items.f64_impl(), lang_items.f64_runtime_impl()), + ty::FloatTy::F32 => (lang_items.f32_impl(), lang_items.f32_runtime_impl()), + ty::FloatTy::F64 => (lang_items.f64_impl(), lang_items.f64_runtime_impl()), }; self.assemble_inherent_impl_for_primitive(lang_def_id1); self.assemble_inherent_impl_for_primitive(lang_def_id2); diff --git a/compiler/rustc_typeck/src/check/upvar.rs b/compiler/rustc_typeck/src/check/upvar.rs index feda35daa617d..6b2cba62fa6b7 100644 --- a/compiler/rustc_typeck/src/check/upvar.rs +++ b/compiler/rustc_typeck/src/check/upvar.rs @@ -42,7 +42,7 @@ use rustc_infer::infer::UpvarRegion; use rustc_middle::hir::place::{Place, PlaceBase, PlaceWithHirId, ProjectionKind}; use rustc_middle::ty::{self, Ty, TyCtxt, UpvarSubsts}; use rustc_span::sym; -use rustc_span::{Span, Symbol}; +use rustc_span::{MultiSpan, Span, Symbol}; /// Describe the relationship between the paths of two places /// eg: @@ -135,7 +135,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let upvar_id = ty::UpvarId::new(var_hir_id, local_def_id); let capture_kind = self.init_capture_kind(capture_clause, upvar_id, span); - let info = ty::CaptureInfo { expr_id: None, capture_kind }; + let info = ty::CaptureInfo { + capture_kind_expr_id: None, + path_expr_id: None, + capture_kind, + }; capture_information.insert(place, info); } @@ -308,8 +312,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Some(capture_kind) = upvar_capture_map.get(&upvar_id) { // upvar_capture_map only stores the UpvarCapture (CaptureKind), // so we create a fake capture info with no expression. - let fake_capture_info = - ty::CaptureInfo { expr_id: None, capture_kind: *capture_kind }; + let fake_capture_info = ty::CaptureInfo { + capture_kind_expr_id: None, + path_expr_id: None, + capture_kind: *capture_kind, + }; determine_capture_info(fake_capture_info, capture_info).capture_kind } else { capture_info.capture_kind @@ -359,20 +366,44 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// /// ``` /// { - /// Place(base: hir_id_s, projections: [], ....) -> (hir_id_L5, ByValue), - /// Place(base: hir_id_p, projections: [Field(0, 0)], ...) -> (hir_id_L2, ByRef(MutBorrow)) - /// Place(base: hir_id_p, projections: [Field(1, 0)], ...) -> (hir_id_L3, ByRef(ImmutBorrow)) - /// Place(base: hir_id_p, projections: [], ...) -> (hir_id_L4, ByRef(ImmutBorrow)) + /// Place(base: hir_id_s, projections: [], ....) -> { + /// capture_kind_expr: hir_id_L5, + /// path_expr_id: hir_id_L5, + /// capture_kind: ByValue + /// }, + /// Place(base: hir_id_p, projections: [Field(0, 0)], ...) -> { + /// capture_kind_expr: hir_id_L2, + /// path_expr_id: hir_id_L2, + /// capture_kind: ByValue + /// }, + /// Place(base: hir_id_p, projections: [Field(1, 0)], ...) -> { + /// capture_kind_expr: hir_id_L3, + /// path_expr_id: hir_id_L3, + /// capture_kind: ByValue + /// }, + /// Place(base: hir_id_p, projections: [], ...) -> { + /// capture_kind_expr: hir_id_L4, + /// path_expr_id: hir_id_L4, + /// capture_kind: ByValue + /// }, /// ``` /// /// After the min capture analysis, we get: /// ``` /// { /// hir_id_s -> [ - /// Place(base: hir_id_s, projections: [], ....) -> (hir_id_L4, ByValue) + /// Place(base: hir_id_s, projections: [], ....) -> { + /// capture_kind_expr: hir_id_L5, + /// path_expr_id: hir_id_L5, + /// capture_kind: ByValue + /// }, /// ], /// hir_id_p -> [ - /// Place(base: hir_id_p, projections: [], ...) -> (hir_id_L2, ByRef(MutBorrow)), + /// Place(base: hir_id_p, projections: [], ...) -> { + /// capture_kind_expr: hir_id_L2, + /// path_expr_id: hir_id_L4, + /// capture_kind: ByValue + /// }, /// ], /// ``` fn compute_min_captures( @@ -425,8 +456,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // current place is ancestor of possible_descendant PlaceAncestryRelation::Ancestor => { descendant_found = true; + let backup_path_expr_id = updated_capture_info.path_expr_id; + updated_capture_info = determine_capture_info(updated_capture_info, possible_descendant.info); + + // we need to keep the ancestor's `path_expr_id` + updated_capture_info.path_expr_id = backup_path_expr_id; false } @@ -441,9 +477,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // current place is descendant of possible_ancestor PlaceAncestryRelation::Descendant => { ancestor_found = true; + let backup_path_expr_id = possible_ancestor.info.path_expr_id; possible_ancestor.info = determine_capture_info(possible_ancestor.info, capture_info); + // we need to keep the ancestor's `path_expr_id` + possible_ancestor.info.path_expr_id = backup_path_expr_id; + // Only one ancestor of the current place will be in the list. break; } @@ -518,7 +558,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let capture_str = construct_capture_info_string(self.tcx, place, capture_info); let output_str = format!("Capturing {}", capture_str); - let span = capture_info.expr_id.map_or(closure_span, |e| self.tcx.hir().span(e)); + let span = + capture_info.path_expr_id.map_or(closure_span, |e| self.tcx.hir().span(e)); diag.span_note(span, &output_str); } diag.emit(); @@ -542,9 +583,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { construct_capture_info_string(self.tcx, place, capture_info); let output_str = format!("Min Capture {}", capture_str); - let span = - capture_info.expr_id.map_or(closure_span, |e| self.tcx.hir().span(e)); - diag.span_note(span, &output_str); + if capture.info.path_expr_id != capture.info.capture_kind_expr_id { + let path_span = capture_info + .path_expr_id + .map_or(closure_span, |e| self.tcx.hir().span(e)); + let capture_kind_span = capture_info + .capture_kind_expr_id + .map_or(closure_span, |e| self.tcx.hir().span(e)); + + let mut multi_span: MultiSpan = + MultiSpan::from_spans(vec![path_span, capture_kind_span]); + + let capture_kind_label = + construct_capture_kind_reason_string(self.tcx, place, capture_info); + let path_label = construct_path_string(self.tcx, place); + + multi_span.push_span_label(path_span, path_label); + multi_span.push_span_label(capture_kind_span, capture_kind_label); + + diag.span_note(multi_span, &output_str); + } else { + let span = capture_info + .path_expr_id + .map_or(closure_span, |e| self.tcx.hir().span(e)); + + diag.span_note(span, &output_str); + }; } } diag.emit(); @@ -642,7 +706,8 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> { ); let capture_info = ty::CaptureInfo { - expr_id: Some(diag_expr_id), + capture_kind_expr_id: Some(diag_expr_id), + path_expr_id: Some(diag_expr_id), capture_kind: ty::UpvarCapture::ByValue(Some(usage_span)), }; @@ -762,7 +827,8 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> { let new_upvar_borrow = ty::UpvarBorrow { kind, region: curr_upvar_borrow.region }; let capture_info = ty::CaptureInfo { - expr_id: Some(diag_expr_id), + capture_kind_expr_id: Some(diag_expr_id), + path_expr_id: Some(diag_expr_id), capture_kind: ty::UpvarCapture::ByRef(new_upvar_borrow), }; let updated_info = determine_capture_info(curr_capture_info, capture_info); @@ -824,7 +890,11 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> { self.fcx.init_capture_kind(self.capture_clause, upvar_id, self.closure_span); let expr_id = Some(diag_expr_id); - let capture_info = ty::CaptureInfo { expr_id, capture_kind }; + let capture_info = ty::CaptureInfo { + capture_kind_expr_id: expr_id, + path_expr_id: expr_id, + capture_kind, + }; debug!("Capturing new place {:?}, capture_info={:?}", place_with_id, capture_info); @@ -890,11 +960,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'tcx> { } } -fn construct_capture_info_string( - tcx: TyCtxt<'_>, - place: &Place<'tcx>, - capture_info: &ty::CaptureInfo<'tcx>, -) -> String { +fn construct_place_string(tcx: TyCtxt<'_>, place: &Place<'tcx>) -> String { let variable_name = match place.base { PlaceBase::Upvar(upvar_id) => var_name(tcx, upvar_id.var_path.hir_id).to_string(), _ => bug!("Capture_information should only contain upvars"), @@ -914,11 +980,42 @@ fn construct_capture_info_string( projections_str.push_str(proj.as_str()); } + format!("{}[{}]", variable_name, projections_str) +} + +fn construct_capture_kind_reason_string( + tcx: TyCtxt<'_>, + place: &Place<'tcx>, + capture_info: &ty::CaptureInfo<'tcx>, +) -> String { + let place_str = construct_place_string(tcx, &place); + let capture_kind_str = match capture_info.capture_kind { ty::UpvarCapture::ByValue(_) => "ByValue".into(), ty::UpvarCapture::ByRef(borrow) => format!("{:?}", borrow.kind), }; - format!("{}[{}] -> {}", variable_name, projections_str, capture_kind_str) + + format!("{} captured as {} here", place_str, capture_kind_str) +} + +fn construct_path_string(tcx: TyCtxt<'_>, place: &Place<'tcx>) -> String { + let place_str = construct_place_string(tcx, &place); + + format!("{} used here", place_str) +} + +fn construct_capture_info_string( + tcx: TyCtxt<'_>, + place: &Place<'tcx>, + capture_info: &ty::CaptureInfo<'tcx>, +) -> String { + let place_str = construct_place_string(tcx, &place); + + let capture_kind_str = match capture_info.capture_kind { + ty::UpvarCapture::ByValue(_) => "ByValue".into(), + ty::UpvarCapture::ByRef(borrow) => format!("{:?}", borrow.kind), + }; + format!("{} -> {}", place_str, capture_kind_str) } fn var_name(tcx: TyCtxt<'_>, var_hir_id: hir::HirId) -> Symbol { @@ -930,7 +1027,9 @@ fn var_name(tcx: TyCtxt<'_>, var_hir_id: hir::HirId) -> Symbol { /// (Note: CaptureInfo contains CaptureKind and an expression that led to capture it in that way) /// /// If both `CaptureKind`s are considered equivalent, then the CaptureInfo is selected based -/// on the `CaptureInfo` containing an associated expression id. +/// on the `CaptureInfo` containing an associated `capture_kind_expr_id`. +/// +/// It is the caller's duty to figure out which path_expr_id to use. /// /// If both the CaptureKind and Expression are considered to be equivalent, /// then `CaptureInfo` A is preferred. This can be useful in cases where we want to priortize @@ -981,7 +1080,7 @@ fn determine_capture_info( }; if eq_capture_kind { - match (capture_info_a.expr_id, capture_info_b.expr_id) { + match (capture_info_a.capture_kind_expr_id, capture_info_b.capture_kind_expr_id) { (Some(_), _) | (None, None) => capture_info_a, (None, Some(_)) => capture_info_b, } diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs index 9e6bf5ce52d8a..b6d740a4fdb57 100644 --- a/compiler/rustc_typeck/src/check/writeback.rs +++ b/compiler/rustc_typeck/src/check/writeback.rs @@ -348,7 +348,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { let min_list_wb = min_list .iter() .map(|captured_place| { - let locatable = captured_place.info.expr_id.unwrap_or( + let locatable = captured_place.info.path_expr_id.unwrap_or( self.tcx().hir().local_def_id_to_hir_id(closure_def_id.expect_local()), ); diff --git a/compiler/rustc_typeck/src/coherence/inherent_impls.rs b/compiler/rustc_typeck/src/coherence/inherent_impls.rs index 6b6c66932c868..8a500852a0326 100644 --- a/compiler/rustc_typeck/src/coherence/inherent_impls.rs +++ b/compiler/rustc_typeck/src/coherence/inherent_impls.rs @@ -13,7 +13,6 @@ use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE}; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_middle::ty::{self, CrateInherentImpls, TyCtxt}; -use rustc_ast as ast; use rustc_span::Span; /// On-demand query: yields a map containing all types mapped to their inherent impls. @@ -178,7 +177,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> { assoc_items, ); } - ty::Int(ast::IntTy::I8) => { + ty::Int(ty::IntTy::I8) => { self.check_primitive_impl( def_id, lang_items.i8_impl(), @@ -189,7 +188,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> { assoc_items, ); } - ty::Int(ast::IntTy::I16) => { + ty::Int(ty::IntTy::I16) => { self.check_primitive_impl( def_id, lang_items.i16_impl(), @@ -200,7 +199,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> { assoc_items, ); } - ty::Int(ast::IntTy::I32) => { + ty::Int(ty::IntTy::I32) => { self.check_primitive_impl( def_id, lang_items.i32_impl(), @@ -211,7 +210,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> { assoc_items, ); } - ty::Int(ast::IntTy::I64) => { + ty::Int(ty::IntTy::I64) => { self.check_primitive_impl( def_id, lang_items.i64_impl(), @@ -222,7 +221,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> { assoc_items, ); } - ty::Int(ast::IntTy::I128) => { + ty::Int(ty::IntTy::I128) => { self.check_primitive_impl( def_id, lang_items.i128_impl(), @@ -233,7 +232,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> { assoc_items, ); } - ty::Int(ast::IntTy::Isize) => { + ty::Int(ty::IntTy::Isize) => { self.check_primitive_impl( def_id, lang_items.isize_impl(), @@ -244,7 +243,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> { assoc_items, ); } - ty::Uint(ast::UintTy::U8) => { + ty::Uint(ty::UintTy::U8) => { self.check_primitive_impl( def_id, lang_items.u8_impl(), @@ -255,7 +254,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> { assoc_items, ); } - ty::Uint(ast::UintTy::U16) => { + ty::Uint(ty::UintTy::U16) => { self.check_primitive_impl( def_id, lang_items.u16_impl(), @@ -266,7 +265,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> { assoc_items, ); } - ty::Uint(ast::UintTy::U32) => { + ty::Uint(ty::UintTy::U32) => { self.check_primitive_impl( def_id, lang_items.u32_impl(), @@ -277,7 +276,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> { assoc_items, ); } - ty::Uint(ast::UintTy::U64) => { + ty::Uint(ty::UintTy::U64) => { self.check_primitive_impl( def_id, lang_items.u64_impl(), @@ -288,7 +287,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> { assoc_items, ); } - ty::Uint(ast::UintTy::U128) => { + ty::Uint(ty::UintTy::U128) => { self.check_primitive_impl( def_id, lang_items.u128_impl(), @@ -299,7 +298,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> { assoc_items, ); } - ty::Uint(ast::UintTy::Usize) => { + ty::Uint(ty::UintTy::Usize) => { self.check_primitive_impl( def_id, lang_items.usize_impl(), @@ -310,7 +309,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> { assoc_items, ); } - ty::Float(ast::FloatTy::F32) => { + ty::Float(ty::FloatTy::F32) => { self.check_primitive_impl( def_id, lang_items.f32_impl(), @@ -321,7 +320,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> { assoc_items, ); } - ty::Float(ast::FloatTy::F64) => { + ty::Float(ty::FloatTy::F64) => { self.check_primitive_impl( def_id, lang_items.f64_impl(), diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index d589989511db1..b1d98d75196d5 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -50,8 +50,6 @@ use rustc_span::{Span, DUMMY_SP}; use rustc_target::spec::abi; use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamName; -use std::ops::ControlFlow; - mod item_bounds; mod type_of; @@ -2080,38 +2078,6 @@ fn const_evaluatable_predicates_of<'tcx>( )); } } - - // Look into `TyAlias`. - fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) { - use ty::fold::{TypeFoldable, TypeVisitor}; - struct TyAliasVisitor<'a, 'tcx> { - tcx: TyCtxt<'tcx>, - preds: &'a mut FxIndexSet<(ty::Predicate<'tcx>, Span)>, - span: Span, - } - - impl<'a, 'tcx> TypeVisitor<'tcx> for TyAliasVisitor<'a, 'tcx> { - fn visit_const(&mut self, ct: &'tcx Const<'tcx>) -> ControlFlow { - if let ty::ConstKind::Unevaluated(def, substs, None) = ct.val { - self.preds.insert(( - ty::PredicateKind::ConstEvaluatable(def, substs).to_predicate(self.tcx), - self.span, - )); - } - ControlFlow::CONTINUE - } - } - - if let hir::TyKind::Path(hir::QPath::Resolved(None, path)) = ty.kind { - if let Res::Def(DefKind::TyAlias, def_id) = path.res { - let mut visitor = - TyAliasVisitor { tcx: self.tcx, preds: &mut self.preds, span: path.span }; - self.tcx.type_of(def_id).visit_with(&mut visitor); - } - } - - intravisit::walk_ty(self, ty) - } } let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); diff --git a/compiler/rustc_typeck/src/expr_use_visitor.rs b/compiler/rustc_typeck/src/expr_use_visitor.rs index 24364c6954e49..bd2c266d93dca 100644 --- a/compiler/rustc_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_typeck/src/expr_use_visitor.rs @@ -630,7 +630,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { PlaceBase::Local(*var_hir_id) }; let place_with_id = PlaceWithHirId::new( - capture_info.expr_id.unwrap_or(closure_expr.hir_id), + capture_info.path_expr_id.unwrap_or(closure_expr.hir_id), place.base_ty, place_base, place.projections.clone(), diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs index 139863bbe7f81..a6d3b5ef813f1 100644 --- a/library/core/src/convert/mod.rs +++ b/library/core/src/convert/mod.rs @@ -267,6 +267,7 @@ pub trait AsMut { /// /// [`String`]: ../../std/string/struct.String.html /// [`Vec`]: ../../std/vec/struct.Vec.html +#[rustc_diagnostic_item = "into_trait"] #[stable(feature = "rust1", since = "1.0.0")] pub trait Into: Sized { /// Performs the conversion. @@ -382,6 +383,7 @@ pub trait From: Sized { /// /// This suffers the same restrictions and reasoning as implementing /// [`Into`], see there for details. +#[rustc_diagnostic_item = "try_into_trait"] #[stable(feature = "try_from", since = "1.34.0")] pub trait TryInto: Sized { /// The type returned in the event of a conversion error. @@ -462,6 +464,7 @@ pub trait TryInto: Sized { /// /// [`try_from`]: TryFrom::try_from /// [`!`]: ../../std/primitive.never.html +#[rustc_diagnostic_item = "try_from_trait"] #[stable(feature = "try_from", since = "1.34.0")] pub trait TryFrom: Sized { /// The type returned in the event of a conversion error. diff --git a/library/core/src/iter/adapters/flatten.rs b/library/core/src/iter/adapters/flatten.rs index 29e191db0f62f..081f282edcf89 100644 --- a/library/core/src/iter/adapters/flatten.rs +++ b/library/core/src/iter/adapters/flatten.rs @@ -265,7 +265,13 @@ where } } match self.iter.next() { - None => return self.backiter.as_mut()?.next(), + None => match self.backiter.as_mut()?.next() { + None => { + self.backiter = None; + return None; + } + elt @ Some(_) => return elt, + }, Some(inner) => self.frontiter = Some(inner.into_iter()), } } @@ -353,7 +359,13 @@ where } } match self.iter.next_back() { - None => return self.frontiter.as_mut()?.next_back(), + None => match self.frontiter.as_mut()?.next_back() { + None => { + self.frontiter = None; + return None; + } + elt @ Some(_) => return elt, + }, next => self.backiter = next.map(IntoIterator::into_iter), } } diff --git a/library/core/tests/iter/adapters/flatten.rs b/library/core/tests/iter/adapters/flatten.rs index bd2c6fd9252df..4bbae6947bf66 100644 --- a/library/core/tests/iter/adapters/flatten.rs +++ b/library/core/tests/iter/adapters/flatten.rs @@ -64,6 +64,14 @@ fn test_flatten_non_fused_outer() { assert_eq!(iter.next_back(), Some(1)); assert_eq!(iter.next(), Some(0)); assert_eq!(iter.next(), None); + assert_eq!(iter.next(), None); + + let mut iter = NonFused::new(once(0..2)).flatten(); + + assert_eq!(iter.next(), Some(0)); + assert_eq!(iter.next_back(), Some(1)); + assert_eq!(iter.next_back(), None); + assert_eq!(iter.next_back(), None); } #[test] @@ -74,6 +82,15 @@ fn test_flatten_non_fused_inner() { assert_eq!(iter.next(), Some(0)); assert_eq!(iter.next(), Some(1)); assert_eq!(iter.next(), None); + assert_eq!(iter.next(), None); + + let mut iter = once(0..1).chain(once(1..3)).flat_map(NonFused::new); + + assert_eq!(iter.next(), Some(0)); + assert_eq!(iter.next_back(), Some(2)); + assert_eq!(iter.next_back(), Some(1)); + assert_eq!(iter.next_back(), None); + assert_eq!(iter.next_back(), None); } #[test] diff --git a/library/std/src/io/buffered/bufreader.rs b/library/std/src/io/buffered/bufreader.rs index 8bae3da1273eb..987371f50ec22 100644 --- a/library/std/src/io/buffered/bufreader.rs +++ b/library/std/src/io/buffered/bufreader.rs @@ -410,7 +410,6 @@ impl Seek for BufReader { /// # Example /// /// ```no_run - /// #![feature(seek_convenience)] /// use std::{ /// io::{self, BufRead, BufReader, Seek}, /// fs::File, diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index c87a56586c65e..db3b0e2628f2a 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -1671,7 +1671,7 @@ pub trait Seek { /// # Example /// /// ```no_run - /// #![feature(seek_convenience)] + /// #![feature(seek_stream_len)] /// use std::{ /// io::{self, Seek}, /// fs::File, @@ -1685,7 +1685,7 @@ pub trait Seek { /// Ok(()) /// } /// ``` - #[unstable(feature = "seek_convenience", issue = "59359")] + #[unstable(feature = "seek_stream_len", issue = "59359")] fn stream_len(&mut self) -> Result { let old_pos = self.stream_position()?; let len = self.seek(SeekFrom::End(0))?; @@ -1706,7 +1706,6 @@ pub trait Seek { /// # Example /// /// ```no_run - /// #![feature(seek_convenience)] /// use std::{ /// io::{self, BufRead, BufReader, Seek}, /// fs::File, @@ -1723,7 +1722,7 @@ pub trait Seek { /// Ok(()) /// } /// ``` - #[unstable(feature = "seek_convenience", issue = "59359")] + #[stable(feature = "seek_convenience", since = "1.51.0")] fn stream_position(&mut self) -> Result { self.seek(SeekFrom::Current(0)) } diff --git a/library/test/src/test_result.rs b/library/test/src/test_result.rs index 465f3f8f99427..598fb670bb4bf 100644 --- a/library/test/src/test_result.rs +++ b/library/test/src/test_result.rs @@ -63,7 +63,7 @@ pub fn calc_result<'a>( )) } } - (&ShouldPanic::Yes, Ok(())) => { + (&ShouldPanic::Yes, Ok(())) | (&ShouldPanic::YesWithMessage(_), Ok(())) => { TestResult::TrFailedMsg("test did not panic as expected".to_string()) } _ if desc.allow_fail => TestResult::TrAllowedFail, diff --git a/library/test/src/tests.rs b/library/test/src/tests.rs index 74313cc4438ed..a629829b88514 100644 --- a/library/test/src/tests.rs +++ b/library/test/src/tests.rs @@ -228,21 +228,30 @@ fn test_should_panic_non_string_message_type() { #[test] #[cfg(not(target_os = "emscripten"))] fn test_should_panic_but_succeeds() { - fn f() {} - let desc = TestDescAndFn { - desc: TestDesc { - name: StaticTestName("whatever"), - ignore: false, - should_panic: ShouldPanic::Yes, - allow_fail: false, - test_type: TestType::Unknown, - }, - testfn: DynTestFn(Box::new(f)), - }; - let (tx, rx) = channel(); - run_test(&TestOpts::new(), false, desc, RunStrategy::InProcess, tx, Concurrent::No); - let result = rx.recv().unwrap().result; - assert_eq!(result, TrFailedMsg("test did not panic as expected".to_string())); + let should_panic_variants = [ShouldPanic::Yes, ShouldPanic::YesWithMessage("error message")]; + + for &should_panic in should_panic_variants.iter() { + fn f() {} + let desc = TestDescAndFn { + desc: TestDesc { + name: StaticTestName("whatever"), + ignore: false, + should_panic, + allow_fail: false, + test_type: TestType::Unknown, + }, + testfn: DynTestFn(Box::new(f)), + }; + let (tx, rx) = channel(); + run_test(&TestOpts::new(), false, desc, RunStrategy::InProcess, tx, Concurrent::No); + let result = rx.recv().unwrap().result; + assert_eq!( + result, + TrFailedMsg("test did not panic as expected".to_string()), + "should_panic == {:?}", + should_panic + ); + } } fn report_time_test_template(report_time: bool) -> Option { diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 86bce8b8707a0..bebb746c92d2f 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -11,7 +11,6 @@ use std::{slice, vec}; use rustc_ast::attr; use rustc_ast::util::comments::beautify_doc_string; use rustc_ast::{self as ast, AttrStyle}; -use rustc_ast::{FloatTy, IntTy, UintTy}; use rustc_attr::{ConstStability, Deprecation, Stability, StabilityLevel}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_feature::UnstableFeatures; @@ -21,7 +20,7 @@ use rustc_hir::def_id::{CrateNum, DefId}; use rustc_hir::lang_items::LangItem; use rustc_hir::Mutability; use rustc_index::vec::IndexVec; -use rustc_middle::ty::TyCtxt; +use rustc_middle::ty::{self, TyCtxt}; use rustc_session::Session; use rustc_span::hygiene::MacroKind; use rustc_span::source_map::DUMMY_SP; @@ -1456,6 +1455,7 @@ impl GetDefId for Type { impl PrimitiveType { crate fn from_hir(prim: hir::PrimTy) -> PrimitiveType { + use ast::{FloatTy, IntTy, UintTy}; match prim { hir::PrimTy::Int(IntTy::Isize) => PrimitiveType::Isize, hir::PrimTy::Int(IntTy::I8) => PrimitiveType::I8, @@ -1690,6 +1690,41 @@ impl From for PrimitiveType { } } +impl From for PrimitiveType { + fn from(int_ty: ty::IntTy) -> PrimitiveType { + match int_ty { + ty::IntTy::Isize => PrimitiveType::Isize, + ty::IntTy::I8 => PrimitiveType::I8, + ty::IntTy::I16 => PrimitiveType::I16, + ty::IntTy::I32 => PrimitiveType::I32, + ty::IntTy::I64 => PrimitiveType::I64, + ty::IntTy::I128 => PrimitiveType::I128, + } + } +} + +impl From for PrimitiveType { + fn from(uint_ty: ty::UintTy) -> PrimitiveType { + match uint_ty { + ty::UintTy::Usize => PrimitiveType::Usize, + ty::UintTy::U8 => PrimitiveType::U8, + ty::UintTy::U16 => PrimitiveType::U16, + ty::UintTy::U32 => PrimitiveType::U32, + ty::UintTy::U64 => PrimitiveType::U64, + ty::UintTy::U128 => PrimitiveType::U128, + } + } +} + +impl From for PrimitiveType { + fn from(float_ty: ty::FloatTy) -> PrimitiveType { + match float_ty { + ty::FloatTy::F32 => PrimitiveType::F32, + ty::FloatTy::F64 => PrimitiveType::F64, + } + } +} + impl From for PrimitiveType { fn from(prim_ty: hir::PrimTy) -> PrimitiveType { match prim_ty { diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 869d48fc25e07..50ec6e69fbd40 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -487,12 +487,16 @@ crate fn get_auto_trait_and_blanket_impls( ty: Ty<'tcx>, param_env_def_id: DefId, ) -> impl Iterator { - let auto_impls = cx.sess().time("get_auto_trait_impls", || { - AutoTraitFinder::new(cx).get_auto_trait_impls(ty, param_env_def_id) - }); - let blanket_impls = cx.sess().time("get_blanket_impls", || { - BlanketImplFinder::new(cx).get_blanket_impls(ty, param_env_def_id) - }); + let auto_impls = cx + .sess() + .prof + .generic_activity("get_auto_trait_impls") + .run(|| AutoTraitFinder::new(cx).get_auto_trait_impls(ty, param_env_def_id)); + let blanket_impls = cx + .sess() + .prof + .generic_activity("get_blanket_impls") + .run(|| BlanketImplFinder::new(cx).get_blanket_impls(ty, param_env_def_id)); auto_impls.into_iter().chain(blanket_impls) } diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 53f0831852456..7e613220f2d69 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -91,6 +91,11 @@ function getThemePickerElement() { return document.getElementById("theme-picker"); } +// Returns the current URL without any query parameter or hash. +function getNakedUrl() { + return window.location.href.split("?")[0].split("#")[0]; +} + // Sets the focus on the search bar at the top of the page function focusSearchBar() { getSearchInput().focus(); @@ -252,7 +257,9 @@ function defocusSearchBar() { hideSearchResults(search); var hash = ev.newURL.slice(ev.newURL.indexOf("#") + 1); if (browserSupportsHistoryApi()) { - history.replaceState(hash, "", "?search=#" + hash); + // `window.location.search`` contains all the query parameters, not just `search`. + history.replaceState(hash, "", + getNakedUrl() + window.location.search + "#" + hash); } elem = document.getElementById(hash); if (elem) { @@ -1810,10 +1817,12 @@ function defocusSearchBar() { // Because searching is incremental by character, only the most // recent search query is added to the browser history. if (browserSupportsHistoryApi()) { + var newURL = getNakedUrl() + "?search=" + encodeURIComponent(query.raw) + + window.location.hash; if (!history.state && !params.search) { - history.pushState(query, "", "?search=" + encodeURIComponent(query.raw)); + history.pushState(query, "", newURL); } else { - history.replaceState(query, "", "?search=" + encodeURIComponent(query.raw)); + history.replaceState(query, "", newURL); } } @@ -1922,7 +1931,8 @@ function defocusSearchBar() { clearInputTimeout(); if (search_input.value.length === 0) { if (browserSupportsHistoryApi()) { - history.replaceState("", window.currentCrate + " - Rust", "?search="); + history.replaceState("", window.currentCrate + " - Rust", + getNakedUrl() + window.location.hash); } hideSearchResults(); } else { @@ -2779,9 +2789,9 @@ function defocusSearchBar() { if (search_input.value !== "" && hasClass(search, "hidden")) { showSearchResults(search); if (browserSupportsHistoryApi()) { - history.replaceState(search_input.value, - "", - "?search=" + encodeURIComponent(search_input.value)); + var extra = "?search=" + encodeURIComponent(search_input.value); + history.replaceState(search_input.value, "", + getNakedUrl() + extra + window.location.hash); } document.title = searchTitle; } diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs index 7b5e9e5905f33..6ec6620681bf5 100644 --- a/src/librustdoc/passes/collect_trait_impls.rs +++ b/src/librustdoc/passes/collect_trait_impls.rs @@ -30,7 +30,7 @@ crate fn collect_trait_impls(krate: Crate, cx: &DocContext<'_>) -> Crate { for &cnum in cx.tcx.crates().iter() { for &(did, _) in cx.tcx.all_trait_implementations(cnum).iter() { - cx.tcx.sess.time("build_extern_trait_impl", || { + cx.tcx.sess.prof.generic_activity("build_extern_trait_impl").run(|| { inline::build_impl(cx, None, did, None, &mut new_items); }); } @@ -39,7 +39,7 @@ crate fn collect_trait_impls(krate: Crate, cx: &DocContext<'_>) -> Crate { // Also try to inline primitive impls from other crates. for &def_id in PrimitiveType::all_impls(cx.tcx).values().flatten() { if !def_id.is_local() { - cx.sess().time("build_primitive_trait_impl", || { + cx.tcx.sess.prof.generic_activity("build_primitive_trait_impls").run(|| { inline::build_impl(cx, None, def_id, None, &mut new_items); // FIXME(eddyb) is this `doc(hidden)` check needed? @@ -59,7 +59,7 @@ crate fn collect_trait_impls(krate: Crate, cx: &DocContext<'_>) -> Crate { for &trait_did in cx.tcx.all_traits(LOCAL_CRATE).iter() { for &impl_node in cx.tcx.hir().trait_impls(trait_did) { let impl_did = cx.tcx.hir().local_def_id(impl_node); - cx.tcx.sess.time("build_local_trait_impl", || { + cx.tcx.sess.prof.generic_activity("build_local_trait_impl").run(|| { let mut extra_attrs = Vec::new(); let mut parent = cx.tcx.parent(impl_did.to_def_id()); while let Some(did) = parent { @@ -177,13 +177,11 @@ impl<'a, 'tcx> DocFolder for SyntheticImplCollector<'a, 'tcx> { if i.is_struct() || i.is_enum() || i.is_union() { // FIXME(eddyb) is this `doc(hidden)` check needed? if !self.cx.tcx.get_attrs(i.def_id).lists(sym::doc).has_word(sym::hidden) { - self.cx.sess().time("get_auto_trait_and_blanket_synthetic_impls", || { - self.impls.extend(get_auto_trait_and_blanket_impls( - self.cx, - self.cx.tcx.type_of(i.def_id), - i.def_id, - )); - }); + self.impls.extend(get_auto_trait_and_blanket_impls( + self.cx, + self.cx.tcx.type_of(i.def_id), + i.def_id, + )); } } diff --git a/src/test/ui/associated-consts/defaults-not-assumed-fail.rs b/src/test/ui/associated-consts/defaults-not-assumed-fail.rs index d7a48cbd63ecc..b0a4c7722e3ce 100644 --- a/src/test/ui/associated-consts/defaults-not-assumed-fail.rs +++ b/src/test/ui/associated-consts/defaults-not-assumed-fail.rs @@ -31,7 +31,7 @@ impl Tr for u32 { fn main() { assert_eq!(<() as Tr>::A, 255); assert_eq!(<() as Tr>::B, 0); // causes the error above - //~^ ERROR evaluation of constant expression failed + //~^ ERROR evaluation of constant value failed //~| ERROR erroneous constant used assert_eq!(::A, 254); diff --git a/src/test/ui/associated-consts/defaults-not-assumed-fail.stderr b/src/test/ui/associated-consts/defaults-not-assumed-fail.stderr index 1497633c26af9..cbaaed0508b98 100644 --- a/src/test/ui/associated-consts/defaults-not-assumed-fail.stderr +++ b/src/test/ui/associated-consts/defaults-not-assumed-fail.stderr @@ -8,15 +8,11 @@ LL | const B: u8 = Self::A + 1; | = note: `#[deny(const_err)]` on by default -error[E0080]: evaluation of constant expression failed - --> $DIR/defaults-not-assumed-fail.rs:33:5 +error[E0080]: evaluation of constant value failed + --> $DIR/defaults-not-assumed-fail.rs:33:16 | LL | assert_eq!(<() as Tr>::B, 0); // causes the error above - | ^^^^^^^^^^^-------------^^^^^ - | | - | referenced constant has errors - | - = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + | ^^^^^^^^^^^^^ referenced constant has errors error: erroneous constant used --> $DIR/defaults-not-assumed-fail.rs:33:5 diff --git a/src/test/ui/borrowck/borrow-raw-address-of-mutability.stderr b/src/test/ui/borrowck/borrow-raw-address-of-mutability.stderr index 44dde0fd80b0d..ea74fb966846f 100644 --- a/src/test/ui/borrowck/borrow-raw-address-of-mutability.stderr +++ b/src/test/ui/borrowck/borrow-raw-address-of-mutability.stderr @@ -20,7 +20,9 @@ error[E0596]: cannot borrow `f` as mutable, as it is not declared as mutable | LL | let f = || { | - help: consider changing this to be mutable: `mut f` -... +LL | let y = &raw mut x; + | - calling `f` requires mutable binding due to mutable borrow of `x` +LL | }; LL | f(); | ^ cannot borrow as mutable diff --git a/src/test/ui/closures/2229_closure_analysis/capture-analysis-1.rs b/src/test/ui/closures/2229_closure_analysis/capture-analysis-1.rs new file mode 100644 index 0000000000000..4368c830e1c61 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/capture-analysis-1.rs @@ -0,0 +1,35 @@ +#![feature(capture_disjoint_fields)] +//~^ WARNING: the feature `capture_disjoint_fields` is incomplete +//~| NOTE: `#[warn(incomplete_features)]` on by default +//~| NOTE: see issue #53488 +#![feature(rustc_attrs)] + +#[derive(Debug)] +struct Point { + x: i32, + y: i32, +} + +fn main() { + let p = Point { x: 10, y: 10 }; + let q = Point { x: 10, y: 10 }; + + let c = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + || { + //~^ First Pass analysis includes: + //~| Min Capture analysis includes: + println!("{:?}", p); + //~^ NOTE: Capturing p[] -> ImmBorrow + //~| NOTE: Min Capture p[] -> ImmBorrow + println!("{:?}", p.x); + //~^ NOTE: Capturing p[(0, 0)] -> ImmBorrow + + println!("{:?}", q.x); + //~^ NOTE: Capturing q[(0, 0)] -> ImmBorrow + println!("{:?}", q); + //~^ NOTE: Capturing q[] -> ImmBorrow + //~| NOTE: Min Capture q[] -> ImmBorrow + }; +} diff --git a/src/test/ui/closures/2229_closure_analysis/capture-analysis-1.stderr b/src/test/ui/closures/2229_closure_analysis/capture-analysis-1.stderr new file mode 100644 index 0000000000000..09255343af0e8 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/capture-analysis-1.stderr @@ -0,0 +1,77 @@ +error[E0658]: attributes on expressions are experimental + --> $DIR/capture-analysis-1.rs:17:13 + | +LL | let c = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/capture-analysis-1.rs:1:12 + | +LL | #![feature(capture_disjoint_fields)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #53488 for more information + +error: First Pass analysis includes: + --> $DIR/capture-analysis-1.rs:20:5 + | +LL | / || { +LL | | +LL | | +LL | | println!("{:?}", p); +... | +LL | | +LL | | }; + | |_____^ + | +note: Capturing p[] -> ImmBorrow + --> $DIR/capture-analysis-1.rs:23:26 + | +LL | println!("{:?}", p); + | ^ +note: Capturing p[(0, 0)] -> ImmBorrow + --> $DIR/capture-analysis-1.rs:26:26 + | +LL | println!("{:?}", p.x); + | ^^^ +note: Capturing q[(0, 0)] -> ImmBorrow + --> $DIR/capture-analysis-1.rs:29:26 + | +LL | println!("{:?}", q.x); + | ^^^ +note: Capturing q[] -> ImmBorrow + --> $DIR/capture-analysis-1.rs:31:26 + | +LL | println!("{:?}", q); + | ^ + +error: Min Capture analysis includes: + --> $DIR/capture-analysis-1.rs:20:5 + | +LL | / || { +LL | | +LL | | +LL | | println!("{:?}", p); +... | +LL | | +LL | | }; + | |_____^ + | +note: Min Capture p[] -> ImmBorrow + --> $DIR/capture-analysis-1.rs:23:26 + | +LL | println!("{:?}", p); + | ^ +note: Min Capture q[] -> ImmBorrow + --> $DIR/capture-analysis-1.rs:31:26 + | +LL | println!("{:?}", q); + | ^ + +error: aborting due to 3 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/closures/2229_closure_analysis/capture-analysis-2.rs b/src/test/ui/closures/2229_closure_analysis/capture-analysis-2.rs new file mode 100644 index 0000000000000..ab7fce6a43099 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/capture-analysis-2.rs @@ -0,0 +1,30 @@ +#![feature(capture_disjoint_fields)] +//~^ WARNING: the feature `capture_disjoint_fields` is incomplete +//~| NOTE: `#[warn(incomplete_features)]` on by default +//~| NOTE: see issue #53488 +#![feature(rustc_attrs)] + +#[derive(Debug)] +struct Point { + x: String, + y: i32, +} + +fn main() { + let mut p = Point { x: String::new(), y: 10 }; + + let c = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + || { + //~^ First Pass analysis includes: + //~| Min Capture analysis includes: + let _x = p.x; + //~^ NOTE: Capturing p[(0, 0)] -> ByValue + //~| NOTE: p[] captured as ByValue here + println!("{:?}", p); + //~^ NOTE: Capturing p[] -> ImmBorrow + //~| NOTE: Min Capture p[] -> ByValue + //~| NOTE: p[] used here + }; +} diff --git a/src/test/ui/closures/2229_closure_analysis/capture-analysis-2.stderr b/src/test/ui/closures/2229_closure_analysis/capture-analysis-2.stderr new file mode 100644 index 0000000000000..0e48d6b300b72 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/capture-analysis-2.stderr @@ -0,0 +1,65 @@ +error[E0658]: attributes on expressions are experimental + --> $DIR/capture-analysis-2.rs:16:13 + | +LL | let c = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/capture-analysis-2.rs:1:12 + | +LL | #![feature(capture_disjoint_fields)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #53488 for more information + +error: First Pass analysis includes: + --> $DIR/capture-analysis-2.rs:19:5 + | +LL | / || { +LL | | +LL | | +LL | | let _x = p.x; +... | +LL | | +LL | | }; + | |_____^ + | +note: Capturing p[(0, 0)] -> ByValue + --> $DIR/capture-analysis-2.rs:22:18 + | +LL | let _x = p.x; + | ^^^ +note: Capturing p[] -> ImmBorrow + --> $DIR/capture-analysis-2.rs:25:26 + | +LL | println!("{:?}", p); + | ^ + +error: Min Capture analysis includes: + --> $DIR/capture-analysis-2.rs:19:5 + | +LL | / || { +LL | | +LL | | +LL | | let _x = p.x; +... | +LL | | +LL | | }; + | |_____^ + | +note: Min Capture p[] -> ByValue + --> $DIR/capture-analysis-2.rs:22:18 + | +LL | let _x = p.x; + | ^^^ p[] captured as ByValue here +... +LL | println!("{:?}", p); + | ^ p[] used here + +error: aborting due to 3 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/closures/2229_closure_analysis/capture-analysis-3.rs b/src/test/ui/closures/2229_closure_analysis/capture-analysis-3.rs new file mode 100644 index 0000000000000..817ade899e2a0 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/capture-analysis-3.rs @@ -0,0 +1,35 @@ +#![feature(capture_disjoint_fields)] +//~^ WARNING: the feature `capture_disjoint_fields` is incomplete +//~| NOTE: `#[warn(incomplete_features)]` on by default +//~| NOTE: see issue #53488 +#![feature(rustc_attrs)] + +#[derive(Debug)] +struct Child { + c: String, + d: String, +} + +#[derive(Debug)] +struct Parent { + b: Child, +} + +fn main() { + let mut a = Parent { b: Child {c: String::new(), d: String::new()} }; + + let c = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + || { + //~^ First Pass analysis includes: + //~| Min Capture analysis includes: + let _x = a.b.c; + //~^ NOTE: Capturing a[(0, 0),(0, 0)] -> ByValue + //~| NOTE: a[(0, 0)] captured as ByValue here + println!("{:?}", a.b); + //~^ NOTE: Capturing a[(0, 0)] -> ImmBorrow + //~| NOTE: Min Capture a[(0, 0)] -> ByValue + //~| NOTE: a[(0, 0)] used here + }; +} diff --git a/src/test/ui/closures/2229_closure_analysis/capture-analysis-3.stderr b/src/test/ui/closures/2229_closure_analysis/capture-analysis-3.stderr new file mode 100644 index 0000000000000..263e9ca56ebf6 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/capture-analysis-3.stderr @@ -0,0 +1,65 @@ +error[E0658]: attributes on expressions are experimental + --> $DIR/capture-analysis-3.rs:21:13 + | +LL | let c = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/capture-analysis-3.rs:1:12 + | +LL | #![feature(capture_disjoint_fields)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #53488 for more information + +error: First Pass analysis includes: + --> $DIR/capture-analysis-3.rs:24:5 + | +LL | / || { +LL | | +LL | | +LL | | let _x = a.b.c; +... | +LL | | +LL | | }; + | |_____^ + | +note: Capturing a[(0, 0),(0, 0)] -> ByValue + --> $DIR/capture-analysis-3.rs:27:18 + | +LL | let _x = a.b.c; + | ^^^^^ +note: Capturing a[(0, 0)] -> ImmBorrow + --> $DIR/capture-analysis-3.rs:30:26 + | +LL | println!("{:?}", a.b); + | ^^^ + +error: Min Capture analysis includes: + --> $DIR/capture-analysis-3.rs:24:5 + | +LL | / || { +LL | | +LL | | +LL | | let _x = a.b.c; +... | +LL | | +LL | | }; + | |_____^ + | +note: Min Capture a[(0, 0)] -> ByValue + --> $DIR/capture-analysis-3.rs:27:18 + | +LL | let _x = a.b.c; + | ^^^^^ a[(0, 0)] captured as ByValue here +... +LL | println!("{:?}", a.b); + | ^^^ a[(0, 0)] used here + +error: aborting due to 3 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/closures/2229_closure_analysis/capture-analysis-4.rs b/src/test/ui/closures/2229_closure_analysis/capture-analysis-4.rs new file mode 100644 index 0000000000000..e8401299b30ad --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/capture-analysis-4.rs @@ -0,0 +1,33 @@ +#![feature(capture_disjoint_fields)] +//~^ WARNING: the feature `capture_disjoint_fields` is incomplete +//~| NOTE: `#[warn(incomplete_features)]` on by default +//~| NOTE: see issue #53488 +#![feature(rustc_attrs)] + +#[derive(Debug)] +struct Child { + c: String, + d: String, +} + +#[derive(Debug)] +struct Parent { + b: Child, +} + +fn main() { + let mut a = Parent { b: Child {c: String::new(), d: String::new()} }; + + let c = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + || { + //~^ First Pass analysis includes: + //~| Min Capture analysis includes: + let _x = a.b; + //~^ NOTE: Capturing a[(0, 0)] -> ByValue + //~| NOTE: Min Capture a[(0, 0)] -> ByValue + println!("{:?}", a.b.c); + //~^ NOTE: Capturing a[(0, 0),(0, 0)] -> ImmBorrow + }; +} diff --git a/src/test/ui/closures/2229_closure_analysis/capture-analysis-4.stderr b/src/test/ui/closures/2229_closure_analysis/capture-analysis-4.stderr new file mode 100644 index 0000000000000..f4605c1d51b76 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/capture-analysis-4.stderr @@ -0,0 +1,62 @@ +error[E0658]: attributes on expressions are experimental + --> $DIR/capture-analysis-4.rs:21:13 + | +LL | let c = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/capture-analysis-4.rs:1:12 + | +LL | #![feature(capture_disjoint_fields)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #53488 for more information + +error: First Pass analysis includes: + --> $DIR/capture-analysis-4.rs:24:5 + | +LL | / || { +LL | | +LL | | +LL | | let _x = a.b; +... | +LL | | +LL | | }; + | |_____^ + | +note: Capturing a[(0, 0)] -> ByValue + --> $DIR/capture-analysis-4.rs:27:18 + | +LL | let _x = a.b; + | ^^^ +note: Capturing a[(0, 0),(0, 0)] -> ImmBorrow + --> $DIR/capture-analysis-4.rs:30:26 + | +LL | println!("{:?}", a.b.c); + | ^^^^^ + +error: Min Capture analysis includes: + --> $DIR/capture-analysis-4.rs:24:5 + | +LL | / || { +LL | | +LL | | +LL | | let _x = a.b; +... | +LL | | +LL | | }; + | |_____^ + | +note: Min Capture a[(0, 0)] -> ByValue + --> $DIR/capture-analysis-4.rs:27:18 + | +LL | let _x = a.b; + | ^^^ + +error: aborting due to 3 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/closures/2229_closure_analysis/deep-multilevel-struct.rs b/src/test/ui/closures/2229_closure_analysis/deep-multilevel-struct.rs new file mode 100644 index 0000000000000..f81866bb7e096 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/deep-multilevel-struct.rs @@ -0,0 +1,52 @@ +#![feature(capture_disjoint_fields)] +//~^ WARNING: the feature `capture_disjoint_fields` is incomplete +//~| NOTE: `#[warn(incomplete_features)]` on by default +//~| NOTE: see issue #53488 +#![feature(rustc_attrs)] +#![allow(unused)] + +#[derive(Debug)] +struct Point { + x: i32, + y: i32, +} +#[derive(Debug)] +struct Line { + p: Point, + q: Point +} +#[derive(Debug)] +struct Plane { + a: Line, + b: Line, +} + +fn main() { + let mut p = Plane { + a: Line { + p: Point { x: 1,y: 2 }, + q: Point { x: 3,y: 4 }, + }, + b: Line { + p: Point { x: 1,y: 2 }, + q: Point { x: 3,y: 4 }, + } + }; + + let c = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + || { + //~^ ERROR: First Pass analysis includes: + //~| ERROR: Min Capture analysis includes: + let x = &p.a.p.x; + //~^ NOTE: Capturing p[(0, 0),(0, 0),(0, 0)] -> ImmBorrow + p.b.q.y = 9; + //~^ NOTE: Capturing p[(1, 0),(1, 0),(1, 0)] -> MutBorrow + //~| NOTE: p[] captured as MutBorrow here + println!("{:?}", p); + //~^ NOTE: Capturing p[] -> ImmBorrow + //~| NOTE: Min Capture p[] -> MutBorrow + //~| NOTE: p[] used here + }; +} diff --git a/src/test/ui/closures/2229_closure_analysis/deep-multilevel-struct.stderr b/src/test/ui/closures/2229_closure_analysis/deep-multilevel-struct.stderr new file mode 100644 index 0000000000000..863f1009131a1 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/deep-multilevel-struct.stderr @@ -0,0 +1,70 @@ +error[E0658]: attributes on expressions are experimental + --> $DIR/deep-multilevel-struct.rs:36:13 + | +LL | let c = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/deep-multilevel-struct.rs:1:12 + | +LL | #![feature(capture_disjoint_fields)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #53488 for more information + +error: First Pass analysis includes: + --> $DIR/deep-multilevel-struct.rs:39:5 + | +LL | / || { +LL | | +LL | | +LL | | let x = &p.a.p.x; +... | +LL | | +LL | | }; + | |_____^ + | +note: Capturing p[(0, 0),(0, 0),(0, 0)] -> ImmBorrow + --> $DIR/deep-multilevel-struct.rs:42:18 + | +LL | let x = &p.a.p.x; + | ^^^^^^^ +note: Capturing p[(1, 0),(1, 0),(1, 0)] -> MutBorrow + --> $DIR/deep-multilevel-struct.rs:44:9 + | +LL | p.b.q.y = 9; + | ^^^^^^^ +note: Capturing p[] -> ImmBorrow + --> $DIR/deep-multilevel-struct.rs:47:26 + | +LL | println!("{:?}", p); + | ^ + +error: Min Capture analysis includes: + --> $DIR/deep-multilevel-struct.rs:39:5 + | +LL | / || { +LL | | +LL | | +LL | | let x = &p.a.p.x; +... | +LL | | +LL | | }; + | |_____^ + | +note: Min Capture p[] -> MutBorrow + --> $DIR/deep-multilevel-struct.rs:44:9 + | +LL | p.b.q.y = 9; + | ^^^^^^^ p[] captured as MutBorrow here +... +LL | println!("{:?}", p); + | ^ p[] used here + +error: aborting due to 3 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/closures/2229_closure_analysis/deep-multilevel-tuple.rs b/src/test/ui/closures/2229_closure_analysis/deep-multilevel-tuple.rs new file mode 100644 index 0000000000000..fb03a02efa09e --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/deep-multilevel-tuple.rs @@ -0,0 +1,27 @@ +#![feature(capture_disjoint_fields)] +//~^ WARNING: the feature `capture_disjoint_fields` is incomplete +//~| NOTE: `#[warn(incomplete_features)]` on by default +//~| NOTE: see issue #53488 +#![feature(rustc_attrs)] +#![allow(unused)] + +fn main() { + let mut t = (((1,2),(3,4)),((5,6),(7,8))); + + let c = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + || { + //~^ ERROR: First Pass analysis includes: + //~| ERROR: Min Capture analysis includes: + let x = &t.0.0.0; + //~^ NOTE: Capturing t[(0, 0),(0, 0),(0, 0)] -> ImmBorrow + t.1.1.1 = 9; + //~^ NOTE: Capturing t[(1, 0),(1, 0),(1, 0)] -> MutBorrow + //~| NOTE: t[] captured as MutBorrow here + println!("{:?}", t); + //~^ NOTE: Min Capture t[] -> MutBorrow + //~| NOTE: Capturing t[] -> ImmBorrow + //~| NOTE: t[] used here + }; +} diff --git a/src/test/ui/closures/2229_closure_analysis/deep-multilevel-tuple.stderr b/src/test/ui/closures/2229_closure_analysis/deep-multilevel-tuple.stderr new file mode 100644 index 0000000000000..252db44473222 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/deep-multilevel-tuple.stderr @@ -0,0 +1,70 @@ +error[E0658]: attributes on expressions are experimental + --> $DIR/deep-multilevel-tuple.rs:11:13 + | +LL | let c = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/deep-multilevel-tuple.rs:1:12 + | +LL | #![feature(capture_disjoint_fields)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #53488 for more information + +error: First Pass analysis includes: + --> $DIR/deep-multilevel-tuple.rs:14:5 + | +LL | / || { +LL | | +LL | | +LL | | let x = &t.0.0.0; +... | +LL | | +LL | | }; + | |_____^ + | +note: Capturing t[(0, 0),(0, 0),(0, 0)] -> ImmBorrow + --> $DIR/deep-multilevel-tuple.rs:17:18 + | +LL | let x = &t.0.0.0; + | ^^^^^^^ +note: Capturing t[(1, 0),(1, 0),(1, 0)] -> MutBorrow + --> $DIR/deep-multilevel-tuple.rs:19:9 + | +LL | t.1.1.1 = 9; + | ^^^^^^^ +note: Capturing t[] -> ImmBorrow + --> $DIR/deep-multilevel-tuple.rs:22:26 + | +LL | println!("{:?}", t); + | ^ + +error: Min Capture analysis includes: + --> $DIR/deep-multilevel-tuple.rs:14:5 + | +LL | / || { +LL | | +LL | | +LL | | let x = &t.0.0.0; +... | +LL | | +LL | | }; + | |_____^ + | +note: Min Capture t[] -> MutBorrow + --> $DIR/deep-multilevel-tuple.rs:19:9 + | +LL | t.1.1.1 = 9; + | ^^^^^^^ t[] captured as MutBorrow here +... +LL | println!("{:?}", t); + | ^ t[] used here + +error: aborting due to 3 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/closures/2229_closure_analysis/simple-struct-min-capture.rs b/src/test/ui/closures/2229_closure_analysis/simple-struct-min-capture.rs index aaff3531e5850..a6b5e12d2ed78 100644 --- a/src/test/ui/closures/2229_closure_analysis/simple-struct-min-capture.rs +++ b/src/test/ui/closures/2229_closure_analysis/simple-struct-min-capture.rs @@ -32,9 +32,11 @@ fn main() { //~| ERROR: Min Capture analysis includes: p.x += 10; //~^ NOTE: Capturing p[(0, 0)] -> MutBorrow - //~| NOTE: Min Capture p[] -> MutBorrow + //~| NOTE: p[] captured as MutBorrow here println!("{:?}", p); //~^ NOTE: Capturing p[] -> ImmBorrow + //~| NOTE: Min Capture p[] -> MutBorrow + //~| NOTE: p[] used here }; c(); diff --git a/src/test/ui/closures/2229_closure_analysis/simple-struct-min-capture.stderr b/src/test/ui/closures/2229_closure_analysis/simple-struct-min-capture.stderr index 30d3d5f504eb9..cbbc879219915 100644 --- a/src/test/ui/closures/2229_closure_analysis/simple-struct-min-capture.stderr +++ b/src/test/ui/closures/2229_closure_analysis/simple-struct-min-capture.stderr @@ -55,7 +55,10 @@ note: Min Capture p[] -> MutBorrow --> $DIR/simple-struct-min-capture.rs:33:9 | LL | p.x += 10; - | ^^^ + | ^^^ p[] captured as MutBorrow here +... +LL | println!("{:?}", p); + | ^ p[] used here error: aborting due to 3 previous errors; 1 warning emitted diff --git a/src/test/ui/closures/issue-80313-mutable-borrow-in-closure.rs b/src/test/ui/closures/issue-80313-mutable-borrow-in-closure.rs new file mode 100644 index 0000000000000..ff210ae06a3bd --- /dev/null +++ b/src/test/ui/closures/issue-80313-mutable-borrow-in-closure.rs @@ -0,0 +1,7 @@ +fn main() { + let mut my_var = false; + let callback = || { + &mut my_var; + }; + callback(); //~ ERROR E0596 +} diff --git a/src/test/ui/closures/issue-80313-mutable-borrow-in-closure.stderr b/src/test/ui/closures/issue-80313-mutable-borrow-in-closure.stderr new file mode 100644 index 0000000000000..bf9e1febdbba4 --- /dev/null +++ b/src/test/ui/closures/issue-80313-mutable-borrow-in-closure.stderr @@ -0,0 +1,14 @@ +error[E0596]: cannot borrow `callback` as mutable, as it is not declared as mutable + --> $DIR/issue-80313-mutable-borrow-in-closure.rs:6:5 + | +LL | let callback = || { + | -------- help: consider changing this to be mutable: `mut callback` +LL | &mut my_var; + | ------ calling `callback` requires mutable binding due to mutable borrow of `my_var` +LL | }; +LL | callback(); + | ^^^^^^^^ cannot borrow as mutable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/src/test/ui/closures/issue-80313-mutable-borrow-in-move-closure.rs b/src/test/ui/closures/issue-80313-mutable-borrow-in-move-closure.rs new file mode 100644 index 0000000000000..8f2d8a676302c --- /dev/null +++ b/src/test/ui/closures/issue-80313-mutable-borrow-in-move-closure.rs @@ -0,0 +1,7 @@ +fn main() { + let mut my_var = false; + let callback = move || { + &mut my_var; + }; + callback(); //~ ERROR E0596 +} diff --git a/src/test/ui/closures/issue-80313-mutable-borrow-in-move-closure.stderr b/src/test/ui/closures/issue-80313-mutable-borrow-in-move-closure.stderr new file mode 100644 index 0000000000000..b67cec6a609f0 --- /dev/null +++ b/src/test/ui/closures/issue-80313-mutable-borrow-in-move-closure.stderr @@ -0,0 +1,14 @@ +error[E0596]: cannot borrow `callback` as mutable, as it is not declared as mutable + --> $DIR/issue-80313-mutable-borrow-in-move-closure.rs:6:5 + | +LL | let callback = move || { + | -------- help: consider changing this to be mutable: `mut callback` +LL | &mut my_var; + | ------ calling `callback` requires mutable binding due to possible mutation of `my_var` +LL | }; +LL | callback(); + | ^^^^^^^^ cannot borrow as mutable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/src/test/ui/closures/issue-80313-mutation-in-closure.rs b/src/test/ui/closures/issue-80313-mutation-in-closure.rs new file mode 100644 index 0000000000000..e082ea562ef22 --- /dev/null +++ b/src/test/ui/closures/issue-80313-mutation-in-closure.rs @@ -0,0 +1,7 @@ +fn main() { + let mut my_var = false; + let callback = || { + my_var = true; + }; + callback(); //~ ERROR E0596 +} diff --git a/src/test/ui/closures/issue-80313-mutation-in-closure.stderr b/src/test/ui/closures/issue-80313-mutation-in-closure.stderr new file mode 100644 index 0000000000000..6e98549f6b84f --- /dev/null +++ b/src/test/ui/closures/issue-80313-mutation-in-closure.stderr @@ -0,0 +1,14 @@ +error[E0596]: cannot borrow `callback` as mutable, as it is not declared as mutable + --> $DIR/issue-80313-mutation-in-closure.rs:6:5 + | +LL | let callback = || { + | -------- help: consider changing this to be mutable: `mut callback` +LL | my_var = true; + | ------ calling `callback` requires mutable binding due to mutable borrow of `my_var` +LL | }; +LL | callback(); + | ^^^^^^^^ cannot borrow as mutable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/src/test/ui/closures/issue-80313-mutation-in-move-closure.rs b/src/test/ui/closures/issue-80313-mutation-in-move-closure.rs new file mode 100644 index 0000000000000..f66bf4e062831 --- /dev/null +++ b/src/test/ui/closures/issue-80313-mutation-in-move-closure.rs @@ -0,0 +1,7 @@ +fn main() { + let mut my_var = false; + let callback = move || { + my_var = true; + }; + callback(); //~ ERROR E0596 +} diff --git a/src/test/ui/closures/issue-80313-mutation-in-move-closure.stderr b/src/test/ui/closures/issue-80313-mutation-in-move-closure.stderr new file mode 100644 index 0000000000000..edd55422a0bd4 --- /dev/null +++ b/src/test/ui/closures/issue-80313-mutation-in-move-closure.stderr @@ -0,0 +1,14 @@ +error[E0596]: cannot borrow `callback` as mutable, as it is not declared as mutable + --> $DIR/issue-80313-mutation-in-move-closure.rs:6:5 + | +LL | let callback = move || { + | -------- help: consider changing this to be mutable: `mut callback` +LL | my_var = true; + | ------ calling `callback` requires mutable binding due to possible mutation of `my_var` +LL | }; +LL | callback(); + | ^^^^^^^^ cannot borrow as mutable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/src/test/ui/const-generics/const_evaluatable_checked/elaborate-trait-pred.rs b/src/test/ui/const-generics/const_evaluatable_checked/elaborate-trait-pred.rs new file mode 100644 index 0000000000000..4a4fd1e33117f --- /dev/null +++ b/src/test/ui/const-generics/const_evaluatable_checked/elaborate-trait-pred.rs @@ -0,0 +1,24 @@ +// run-pass +// Test that we use the elaborated predicates from traits +// to satisfy const evaluatable predicates. +#![feature(const_generics, const_evaluatable_checked)] +#![allow(incomplete_features)] +use std::mem::size_of; + +trait Foo: Sized +where + [(); size_of::()]: Sized, +{ +} + +impl Foo for u64 {} +impl Foo for u32 {} + +fn foo() -> [u8; size_of::()] { + [0; size_of::()] +} + +fn main() { + assert_eq!(foo::(), [0; 4]); + assert_eq!(foo::(), [0; 8]); +} diff --git a/src/test/ui/const-generics/const_evaluatable_checked/simple_fail.full.stderr b/src/test/ui/const-generics/const_evaluatable_checked/simple_fail.full.stderr index c8549f101daf6..acf0a52ce5be1 100644 --- a/src/test/ui/const-generics/const_evaluatable_checked/simple_fail.full.stderr +++ b/src/test/ui/const-generics/const_evaluatable_checked/simple_fail.full.stderr @@ -1,9 +1,15 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/simple_fail.rs:9:48 + | +LL | fn test() -> Arr where [u8; N - 1]: Sized { + | ^^^^^ attempt to compute `0_usize - 1_usize`, which would overflow + error[E0080]: evaluation of constant value failed --> $DIR/simple_fail.rs:6:33 | LL | type Arr = [u8; N - 1]; | ^^^^^ attempt to compute `0_usize - 1_usize`, which would overflow -error: aborting due to previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/const-generics/const_evaluatable_checked/simple_fail.min.stderr b/src/test/ui/const-generics/const_evaluatable_checked/simple_fail.min.stderr index df54b4cbca5bd..fe5463f8acc4a 100644 --- a/src/test/ui/const-generics/const_evaluatable_checked/simple_fail.min.stderr +++ b/src/test/ui/const-generics/const_evaluatable_checked/simple_fail.min.stderr @@ -7,5 +7,14 @@ LL | type Arr = [u8; N - 1]; = help: const parameters may only be used as standalone arguments, i.e. `N` = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions -error: aborting due to previous error +error: generic parameters may not be used in const operations + --> $DIR/simple_fail.rs:9:48 + | +LL | fn test() -> Arr where [u8; N - 1]: Sized { + | ^ cannot perform const operation using `N` + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions + +error: aborting due to 2 previous errors diff --git a/src/test/ui/const-generics/const_evaluatable_checked/simple_fail.rs b/src/test/ui/const-generics/const_evaluatable_checked/simple_fail.rs index 3cbc077f4f146..c9535d04244d8 100644 --- a/src/test/ui/const-generics/const_evaluatable_checked/simple_fail.rs +++ b/src/test/ui/const-generics/const_evaluatable_checked/simple_fail.rs @@ -1,12 +1,14 @@ // revisions: full min #![cfg_attr(full, feature(const_generics))] -#![feature(const_evaluatable_checked)] +#![cfg_attr(full, feature(const_evaluatable_checked))] #![allow(incomplete_features)] type Arr = [u8; N - 1]; //[full]~ ERROR evaluation of constant //[min]~^ ERROR generic parameters may not be used in const operations -fn test() -> Arr where Arr: Sized { +fn test() -> Arr where [u8; N - 1]: Sized { +//[min]~^ ERROR generic parameters may not be used in const operations +//[full]~^^ ERROR evaluation of constant todo!() } diff --git a/src/test/ui/const-generics/const_evaluatable_checked/ty-alias-substitution.rs b/src/test/ui/const-generics/const_evaluatable_checked/ty-alias-substitution.rs new file mode 100644 index 0000000000000..5c768a61be25e --- /dev/null +++ b/src/test/ui/const-generics/const_evaluatable_checked/ty-alias-substitution.rs @@ -0,0 +1,14 @@ +// check-pass +// Test that we correctly substitute generic arguments for type aliases. +#![feature(const_generics, const_evaluatable_checked)] +#![allow(incomplete_features)] + +type Alias = [T; N + 1]; + +fn foo() -> Alias where [u8; M + 1]: Sized { + [0; M + 1] +} + +fn main() { + foo::<0>(); +} diff --git a/src/test/ui/const-generics/issues/issue-69654-run-pass.rs b/src/test/ui/const-generics/issues/issue-69654-run-pass.rs index bbfd2183b06e3..8c0398e8a13ea 100644 --- a/src/test/ui/const-generics/issues/issue-69654-run-pass.rs +++ b/src/test/ui/const-generics/issues/issue-69654-run-pass.rs @@ -1,4 +1,3 @@ -// run-pass #![feature(const_generics)] #![allow(incomplete_features, unused_braces)] @@ -15,4 +14,5 @@ where fn main() { Foo::foo(); + //~^ ERROR no function or associated item } diff --git a/src/test/ui/const-generics/issues/issue-69654-run-pass.stderr b/src/test/ui/const-generics/issues/issue-69654-run-pass.stderr new file mode 100644 index 0000000000000..a95cc0f2a1c32 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-69654-run-pass.stderr @@ -0,0 +1,15 @@ +error[E0599]: no function or associated item named `foo` found for struct `Foo<{_: usize}>` in the current scope + --> $DIR/issue-69654-run-pass.rs:16:10 + | +LL | struct Foo {} + | -------------------------- function or associated item `foo` not found for this +... +LL | Foo::foo(); + | ^^^ function or associated item not found in `Foo<{_: usize}>` + | + = note: the method `foo` exists but the following trait bounds were not satisfied: + `[u8; _]: Bar<[(); _]>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/const-generics/issues/issue-69654.rs b/src/test/ui/const-generics/issues/issue-69654.rs index 7e775999ebd10..38fca98ad4f06 100644 --- a/src/test/ui/const-generics/issues/issue-69654.rs +++ b/src/test/ui/const-generics/issues/issue-69654.rs @@ -15,4 +15,5 @@ where fn main() { Foo::foo(); + //~^ ERROR no function or associated item } diff --git a/src/test/ui/const-generics/issues/issue-69654.stderr b/src/test/ui/const-generics/issues/issue-69654.stderr index 70af7bf25d849..69cd0806fcd42 100644 --- a/src/test/ui/const-generics/issues/issue-69654.stderr +++ b/src/test/ui/const-generics/issues/issue-69654.stderr @@ -4,6 +4,19 @@ error[E0423]: expected value, found type parameter `T` LL | impl Bar for [u8; T] {} | ^ not a value -error: aborting due to previous error +error[E0599]: no function or associated item named `foo` found for struct `Foo<{_: usize}>` in the current scope + --> $DIR/issue-69654.rs:17:10 + | +LL | struct Foo {} + | -------------------------- function or associated item `foo` not found for this +... +LL | Foo::foo(); + | ^^^ function or associated item not found in `Foo<{_: usize}>` + | + = note: the method `foo` exists but the following trait bounds were not satisfied: + `[u8; _]: Bar<[(); _]>` + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0423`. +Some errors have detailed explanations: E0423, E0599. +For more information about an error, try `rustc --explain E0423`. diff --git a/src/test/ui/const-generics/occurs-check/unused-substs-1.rs b/src/test/ui/const-generics/occurs-check/unused-substs-1.rs index f56687ecd9329..6ded9f13bc4fa 100644 --- a/src/test/ui/const-generics/occurs-check/unused-substs-1.rs +++ b/src/test/ui/const-generics/occurs-check/unused-substs-1.rs @@ -1,4 +1,3 @@ -// build-pass #![feature(const_generics)] #![allow(incomplete_features)] @@ -10,5 +9,5 @@ where A: Bar; fn main() { - let _ = A; + let _ = A; //~ERROR the trait bound } diff --git a/src/test/ui/const-generics/occurs-check/unused-substs-1.stderr b/src/test/ui/const-generics/occurs-check/unused-substs-1.stderr new file mode 100644 index 0000000000000..6830288acc0ad --- /dev/null +++ b/src/test/ui/const-generics/occurs-check/unused-substs-1.stderr @@ -0,0 +1,17 @@ +error[E0277]: the trait bound `A<{_: usize}>: Bar<{_: usize}>` is not satisfied + --> $DIR/unused-substs-1.rs:12:13 + | +LL | / struct A +LL | | where +LL | | A: Bar; + | |_________________- required by `A` +... +LL | let _ = A; + | ^ the trait `Bar<{_: usize}>` is not implemented for `A<{_: usize}>` + | + = help: the following implementations were found: + as Bar> + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/const-generics/occurs-check/unused-substs-2.rs b/src/test/ui/const-generics/occurs-check/unused-substs-2.rs index 12444ec5312d9..2d00141fbf70b 100644 --- a/src/test/ui/const-generics/occurs-check/unused-substs-2.rs +++ b/src/test/ui/const-generics/occurs-check/unused-substs-2.rs @@ -1,4 +1,3 @@ -// check-pass #![feature(const_generics)] #![allow(incomplete_features)] @@ -24,4 +23,6 @@ fn main() { // `t` is `ty::Infer(TyVar(_#1t))` // `foo` contains `ty::Infer(TyVar(_#1t))` in its substs t = foo; + //~^ ERROR mismatched types + //~| NOTE cyclic type } diff --git a/src/test/ui/const-generics/occurs-check/unused-substs-2.stderr b/src/test/ui/const-generics/occurs-check/unused-substs-2.stderr new file mode 100644 index 0000000000000..9532fc21a31b7 --- /dev/null +++ b/src/test/ui/const-generics/occurs-check/unused-substs-2.stderr @@ -0,0 +1,9 @@ +error[E0308]: mismatched types + --> $DIR/unused-substs-2.rs:25:9 + | +LL | t = foo; + | ^^^ cyclic type of infinite size + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/const-generics/occurs-check/unused-substs-3.rs b/src/test/ui/const-generics/occurs-check/unused-substs-3.rs index 187e27382fcf2..2e306f8c4c88f 100644 --- a/src/test/ui/const-generics/occurs-check/unused-substs-3.rs +++ b/src/test/ui/const-generics/occurs-check/unused-substs-3.rs @@ -1,4 +1,3 @@ -// check-pass #![feature(const_generics)] #![allow(incomplete_features)] @@ -15,4 +14,6 @@ fn main() { // `t` is `ty::Infer(TyVar(_#1t))` // `foo` contains `ty::Infer(TyVar(_#1t))` in its substs t = foo; + //~^ ERROR mismatched types + //~| NOTE cyclic type } diff --git a/src/test/ui/const-generics/occurs-check/unused-substs-3.stderr b/src/test/ui/const-generics/occurs-check/unused-substs-3.stderr new file mode 100644 index 0000000000000..2551d68f97474 --- /dev/null +++ b/src/test/ui/const-generics/occurs-check/unused-substs-3.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/unused-substs-3.rs:16:9 + | +LL | t = foo; + | ^^^ + | | + | cyclic type of infinite size + | help: try using a conversion method: `foo.to_vec()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/const-generics/occurs-check/unused-substs-4.rs b/src/test/ui/const-generics/occurs-check/unused-substs-4.rs index 8e42ceb6d70e9..9c7f5ab91edb1 100644 --- a/src/test/ui/const-generics/occurs-check/unused-substs-4.rs +++ b/src/test/ui/const-generics/occurs-check/unused-substs-4.rs @@ -1,4 +1,3 @@ -// build-pass #![feature(const_generics)] #![allow(incomplete_features)] @@ -8,5 +7,5 @@ fn bind(value: [u8; N]) -> [u8; 3 + 4] { fn main() { let mut arr = Default::default(); - arr = bind(arr); + arr = bind(arr); //~ ERROR mismatched type } diff --git a/src/test/ui/const-generics/occurs-check/unused-substs-4.stderr b/src/test/ui/const-generics/occurs-check/unused-substs-4.stderr new file mode 100644 index 0000000000000..5685eedbdeca8 --- /dev/null +++ b/src/test/ui/const-generics/occurs-check/unused-substs-4.stderr @@ -0,0 +1,9 @@ +error[E0308]: mismatched types + --> $DIR/unused-substs-4.rs:10:11 + | +LL | arr = bind(arr); + | ^^^^^^^^^ encountered a self-referencing constant + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/consts/const-eval/conditional_array_execution.stderr b/src/test/ui/consts/const-eval/conditional_array_execution.stderr index 65dfbd8097e76..c2adff116ef20 100644 --- a/src/test/ui/consts/const-eval/conditional_array_execution.stderr +++ b/src/test/ui/consts/const-eval/conditional_array_execution.stderr @@ -12,7 +12,7 @@ note: the lint level is defined here LL | #![warn(const_err)] | ^^^^^^^^^ -error[E0080]: evaluation of constant expression failed +error[E0080]: evaluation of constant value failed --> $DIR/conditional_array_execution.rs:11:20 | LL | println!("{}", FOO); diff --git a/src/test/ui/consts/const-eval/const-eval-query-stack.rs b/src/test/ui/consts/const-eval/const-eval-query-stack.rs index 39803c8f257e0..cbfeca2402666 100644 --- a/src/test/ui/consts/const-eval/const-eval-query-stack.rs +++ b/src/test/ui/consts/const-eval/const-eval-query-stack.rs @@ -21,6 +21,6 @@ const X: i32 = 1 / 0; //~WARN any use of this value will cause an error fn main() { let x: &'static i32 = &X; - //~^ ERROR evaluation of constant expression failed + //~^ ERROR evaluation of constant value failed println!("x={}", x); } diff --git a/src/test/ui/consts/const-eval/const-eval-query-stack.stderr b/src/test/ui/consts/const-eval/const-eval-query-stack.stderr index 0016d301e598c..3e727b84aed10 100644 --- a/src/test/ui/consts/const-eval/const-eval-query-stack.stderr +++ b/src/test/ui/consts/const-eval/const-eval-query-stack.stderr @@ -12,13 +12,11 @@ note: the lint level is defined here LL | #[warn(const_err)] | ^^^^^^^^^ -error[E0080]: evaluation of constant expression failed - --> $DIR/const-eval-query-stack.rs:23:27 +error[E0080]: evaluation of constant value failed + --> $DIR/const-eval-query-stack.rs:23:28 | LL | let x: &'static i32 = &X; - | ^- - | | - | referenced constant has errors + | ^ referenced constant has errors query stack during panic: #0 [normalize_generic_arg_after_erasing_regions] normalizing `main::promoted[1]` #1 [optimized_mir] optimizing MIR for `main` diff --git a/src/test/ui/consts/const-eval/const_fn_ptr_fail2.rs b/src/test/ui/consts/const-eval/const_fn_ptr_fail2.rs index f67871e6142ef..0a2532973f423 100644 --- a/src/test/ui/consts/const-eval/const_fn_ptr_fail2.rs +++ b/src/test/ui/consts/const-eval/const_fn_ptr_fail2.rs @@ -18,7 +18,7 @@ const Z: usize = bar(double, 2); // FIXME: should fail to typeck someday fn main() { assert_eq!(Y, 4); - //~^ ERROR evaluation of constant expression failed + //~^ ERROR evaluation of constant value failed assert_eq!(Z, 4); - //~^ ERROR evaluation of constant expression failed + //~^ ERROR evaluation of constant value failed } diff --git a/src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr b/src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr index 822d4af83064e..2afedf30563a6 100644 --- a/src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr +++ b/src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr @@ -1,22 +1,14 @@ -error[E0080]: evaluation of constant expression failed - --> $DIR/const_fn_ptr_fail2.rs:20:5 +error[E0080]: evaluation of constant value failed + --> $DIR/const_fn_ptr_fail2.rs:20:16 | LL | assert_eq!(Y, 4); - | ^^^^^^^^^^^-^^^^^ - | | - | referenced constant has errors - | - = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + | ^ referenced constant has errors -error[E0080]: evaluation of constant expression failed - --> $DIR/const_fn_ptr_fail2.rs:22:5 +error[E0080]: evaluation of constant value failed + --> $DIR/const_fn_ptr_fail2.rs:22:16 | LL | assert_eq!(Z, 4); - | ^^^^^^^^^^^-^^^^^ - | | - | referenced constant has errors - | - = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + | ^ referenced constant has errors warning: skipping const checks | diff --git a/src/test/ui/consts/const-eval/issue-43197.rs b/src/test/ui/consts/const-eval/issue-43197.rs index 9109307632b59..7d1d33288a907 100644 --- a/src/test/ui/consts/const-eval/issue-43197.rs +++ b/src/test/ui/consts/const-eval/issue-43197.rs @@ -12,8 +12,8 @@ fn main() { const Y: u32 = foo(0 - 1); //~^ WARN any use of this value will cause println!("{} {}", X, Y); - //~^ ERROR evaluation of constant expression failed - //~| ERROR evaluation of constant expression failed + //~^ ERROR evaluation of constant value failed + //~| ERROR evaluation of constant value failed //~| WARN erroneous constant used [const_err] //~| WARN erroneous constant used [const_err] } diff --git a/src/test/ui/consts/const-eval/issue-43197.stderr b/src/test/ui/consts/const-eval/issue-43197.stderr index 27e067cedbb5c..8c72b59141687 100644 --- a/src/test/ui/consts/const-eval/issue-43197.stderr +++ b/src/test/ui/consts/const-eval/issue-43197.stderr @@ -20,7 +20,7 @@ LL | const Y: u32 = foo(0 - 1); | | | attempt to compute `0_u32 - 1_u32`, which would overflow -error[E0080]: evaluation of constant expression failed +error[E0080]: evaluation of constant value failed --> $DIR/issue-43197.rs:14:23 | LL | println!("{} {}", X, Y); @@ -32,7 +32,7 @@ warning: erroneous constant used LL | println!("{} {}", X, Y); | ^ referenced constant has errors -error[E0080]: evaluation of constant expression failed +error[E0080]: evaluation of constant value failed --> $DIR/issue-43197.rs:14:26 | LL | println!("{} {}", X, Y); diff --git a/src/test/ui/consts/const-eval/issue-44578.rs b/src/test/ui/consts/const-eval/issue-44578.rs index f9194709dc0b7..79f1301a2f944 100644 --- a/src/test/ui/consts/const-eval/issue-44578.rs +++ b/src/test/ui/consts/const-eval/issue-44578.rs @@ -25,5 +25,5 @@ impl Foo for u16 { fn main() { println!("{}", as Foo>::AMT); - //~^ ERROR evaluation of constant expression failed [E0080] + //~^ ERROR evaluation of constant value failed [E0080] } diff --git a/src/test/ui/consts/const-eval/issue-44578.stderr b/src/test/ui/consts/const-eval/issue-44578.stderr index f4323713e682b..bff9f40f82b35 100644 --- a/src/test/ui/consts/const-eval/issue-44578.stderr +++ b/src/test/ui/consts/const-eval/issue-44578.stderr @@ -1,4 +1,4 @@ -error[E0080]: evaluation of constant expression failed +error[E0080]: evaluation of constant value failed --> $DIR/issue-44578.rs:27:20 | LL | println!("{}", as Foo>::AMT); diff --git a/src/test/ui/consts/const-eval/issue-50814-2.stderr b/src/test/ui/consts/const-eval/issue-50814-2.stderr index ca8885e935090..f929f500cf9fb 100644 --- a/src/test/ui/consts/const-eval/issue-50814-2.stderr +++ b/src/test/ui/consts/const-eval/issue-50814-2.stderr @@ -8,13 +8,11 @@ LL | const BAR: usize = [5, 6, 7][T::BOO]; | = note: `#[deny(const_err)]` on by default -error[E0080]: evaluation of constant expression failed - --> $DIR/issue-50814-2.rs:18:5 +error[E0080]: evaluation of constant value failed + --> $DIR/issue-50814-2.rs:18:6 | LL | & as Foo>::BAR - | ^--------------------- - | | - | referenced constant has errors + | ^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors error: aborting due to 2 previous errors diff --git a/src/test/ui/consts/const-eval/issue-50814.stderr b/src/test/ui/consts/const-eval/issue-50814.stderr index 7327138627648..307fb3c8c9de1 100644 --- a/src/test/ui/consts/const-eval/issue-50814.stderr +++ b/src/test/ui/consts/const-eval/issue-50814.stderr @@ -8,13 +8,11 @@ LL | const MAX: u8 = A::MAX + B::MAX; | = note: `#[deny(const_err)]` on by default -error[E0080]: evaluation of constant expression failed - --> $DIR/issue-50814.rs:20:5 +error[E0080]: evaluation of constant value failed + --> $DIR/issue-50814.rs:20:6 | LL | &Sum::::MAX - | ^----------------- - | | - | referenced constant has errors + | ^^^^^^^^^^^^^^^^^ referenced constant has errors error: aborting due to 2 previous errors diff --git a/src/test/ui/consts/const_unsafe_unreachable_ub.stderr b/src/test/ui/consts/const_unsafe_unreachable_ub.stderr index 31090be090833..6dddc7ff6e9d2 100644 --- a/src/test/ui/consts/const_unsafe_unreachable_ub.stderr +++ b/src/test/ui/consts/const_unsafe_unreachable_ub.stderr @@ -20,15 +20,11 @@ note: the lint level is defined here LL | #[warn(const_err)] | ^^^^^^^^^ -error[E0080]: evaluation of constant expression failed - --> $DIR/const_unsafe_unreachable_ub.rs:17:3 +error[E0080]: evaluation of constant value failed + --> $DIR/const_unsafe_unreachable_ub.rs:17:14 | LL | assert_eq!(BAR, true); - | ^^^^^^^^^^^---^^^^^^^^ - | | - | referenced constant has errors - | - = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + | ^^^ referenced constant has errors error: erroneous constant used --> $DIR/const_unsafe_unreachable_ub.rs:17:3 diff --git a/src/test/ui/consts/issue-55878.stderr b/src/test/ui/consts/issue-55878.stderr index 924910e9cb6df..ede5487b65d39 100644 --- a/src/test/ui/consts/issue-55878.stderr +++ b/src/test/ui/consts/issue-55878.stderr @@ -2,15 +2,12 @@ error[E0080]: values of the type `[u8; SIZE]` are too big for the current archit --> $SRC_DIR/core/src/mem/mod.rs:LL:COL | LL | intrinsics::size_of::() - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | inside `std::mem::size_of::<[u8; SIZE]>` at $SRC_DIR/core/src/mem/mod.rs:LL:COL - | inside `main` at $DIR/issue-55878.rs:7:26 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ inside `std::mem::size_of::<[u8; SIZE]>` at $SRC_DIR/core/src/mem/mod.rs:LL:COL | ::: $DIR/issue-55878.rs:7:26 | LL | println!("Size: {}", std::mem::size_of::<[u8; u64::MAX as usize]>()); - | ---------------------------------------------- + | ---------------------------------------------- inside `main` at $DIR/issue-55878.rs:7:26 error: erroneous constant used --> $DIR/issue-55878.rs:7:26 diff --git a/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.stderr b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.stderr index 5dea424596e9c..a0ed56d4bcf7b 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.stderr @@ -3,6 +3,8 @@ error[E0596]: cannot borrow `tick1` as mutable, as it is not declared as mutable | LL | let tick1 = || { | ----- help: consider changing this to be mutable: `mut tick1` +LL | counter += 1; + | ------- calling `tick1` requires mutable binding due to mutable borrow of `counter` ... LL | tick1(); | ^^^^^ cannot borrow as mutable @@ -12,6 +14,8 @@ error[E0596]: cannot borrow `tick2` as mutable, as it is not declared as mutable | LL | let tick2 = || { | ----- help: consider changing this to be mutable: `mut tick2` +LL | tick1(); + | ----- calling `tick2` requires mutable binding due to mutable borrow of `tick1` ... LL | tick2(); | ^^^^^ cannot borrow as mutable diff --git a/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-missing-mut.stderr b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-missing-mut.stderr index eb398628846dd..27d23e3fa044b 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-missing-mut.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-missing-mut.stderr @@ -2,7 +2,9 @@ error[E0596]: cannot borrow `tick` as mutable, as it is not declared as mutable --> $DIR/unboxed-closures-infer-fnmut-missing-mut.rs:7:5 | LL | let tick = || counter += 1; - | ---- help: consider changing this to be mutable: `mut tick` + | ---- ------- calling `tick` requires mutable binding due to mutable borrow of `counter` + | | + | help: consider changing this to be mutable: `mut tick` LL | tick(); | ^^^^ cannot borrow as mutable diff --git a/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-move-missing-mut.stderr b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-move-missing-mut.stderr index b9d76d9a752ce..c00f986c397a7 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-move-missing-mut.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-move-missing-mut.stderr @@ -2,7 +2,9 @@ error[E0596]: cannot borrow `tick` as mutable, as it is not declared as mutable --> $DIR/unboxed-closures-infer-fnmut-move-missing-mut.rs:7:5 | LL | let tick = move || counter += 1; - | ---- help: consider changing this to be mutable: `mut tick` + | ---- ------- calling `tick` requires mutable binding due to possible mutation of `counter` + | | + | help: consider changing this to be mutable: `mut tick` LL | tick(); | ^^^^ cannot borrow as mutable diff --git a/src/tools/clippy/clippy_lints/src/bytecount.rs b/src/tools/clippy/clippy_lints/src/bytecount.rs index 38a0e27c4cf5b..ac9098a7584d6 100644 --- a/src/tools/clippy/clippy_lints/src/bytecount.rs +++ b/src/tools/clippy/clippy_lints/src/bytecount.rs @@ -2,11 +2,10 @@ use crate::utils::{ contains_name, get_pat_name, match_type, paths, single_segment_path, snippet_with_applicability, span_lint_and_sugg, }; use if_chain::if_chain; -use rustc_ast::ast::UintTy; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty; +use rustc_middle::ty::{self, UintTy}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::sym; use rustc_span::Symbol; diff --git a/src/tools/clippy/clippy_lints/src/consts.rs b/src/tools/clippy/clippy_lints/src/consts.rs index 166eadf86c177..640cffd24a701 100644 --- a/src/tools/clippy/clippy_lints/src/consts.rs +++ b/src/tools/clippy/clippy_lints/src/consts.rs @@ -2,14 +2,14 @@ use crate::utils::{clip, sext, unsext}; use if_chain::if_chain; -use rustc_ast::ast::{FloatTy, LitFloatType, LitKind}; +use rustc_ast::ast::{self, LitFloatType, LitKind}; use rustc_data_structures::sync::Lrc; use rustc_hir::def::{DefKind, Res}; use rustc_hir::{BinOp, BinOpKind, Block, Expr, ExprKind, HirId, QPath, UnOp}; use rustc_lint::LateContext; use rustc_middle::mir::interpret::Scalar; use rustc_middle::ty::subst::{Subst, SubstsRef}; -use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt}; +use rustc_middle::ty::{self, FloatTy, ScalarInt, Ty, TyCtxt}; use rustc_middle::{bug, span_bug}; use rustc_span::symbol::Symbol; use std::cmp::Ordering::{self, Equal}; @@ -167,8 +167,8 @@ pub fn lit_to_constant(lit: &LitKind, ty: Option>) -> Constant { LitKind::Char(c) => Constant::Char(c), LitKind::Int(n, _) => Constant::Int(n), LitKind::Float(ref is, LitFloatType::Suffixed(fty)) => match fty { - FloatTy::F32 => Constant::F32(is.as_str().parse().unwrap()), - FloatTy::F64 => Constant::F64(is.as_str().parse().unwrap()), + ast::FloatTy::F32 => Constant::F32(is.as_str().parse().unwrap()), + ast::FloatTy::F64 => Constant::F64(is.as_str().parse().unwrap()), }, LitKind::Float(ref is, LitFloatType::Unsuffixed) => match ty.expect("type of float is known").kind() { ty::Float(FloatTy::F32) => Constant::F32(is.as_str().parse().unwrap()), diff --git a/src/tools/clippy/clippy_lints/src/default.rs b/src/tools/clippy/clippy_lints/src/default.rs index f7224811e6e79..6fa1378b8c73d 100644 --- a/src/tools/clippy/clippy_lints/src/default.rs +++ b/src/tools/clippy/clippy_lints/src/default.rs @@ -1,5 +1,5 @@ use crate::utils::{ - any_parent_is_automatically_derived, contains_name, match_def_path, paths, qpath_res, snippet_with_macro_callsite, + any_parent_is_automatically_derived, contains_name, match_def_path, paths, snippet_with_macro_callsite, }; use crate::utils::{span_lint_and_note, span_lint_and_sugg}; use if_chain::if_chain; @@ -231,7 +231,7 @@ fn is_expr_default<'tcx>(expr: &'tcx Expr<'tcx>, cx: &LateContext<'tcx>) -> bool if_chain! { if let ExprKind::Call(ref fn_expr, _) = &expr.kind; if let ExprKind::Path(qpath) = &fn_expr.kind; - if let Res::Def(_, def_id) = qpath_res(cx, qpath, fn_expr.hir_id); + if let Res::Def(_, def_id) = cx.qpath_res(qpath, fn_expr.hir_id); then { // right hand side of assignment is `Default::default` match_def_path(cx, def_id, &paths::DEFAULT_TRAIT_METHOD) diff --git a/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs b/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs index cf528d189b4b1..a84f9c4628716 100644 --- a/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs +++ b/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs @@ -1,4 +1,4 @@ -use crate::utils::{is_copy, match_def_path, paths, qpath_res, span_lint_and_note}; +use crate::utils::{is_copy, match_def_path, paths, span_lint_and_note}; use if_chain::if_chain; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; @@ -114,7 +114,7 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetRef { if let ExprKind::Call(ref path, ref args) = expr.kind; if let ExprKind::Path(ref qpath) = path.kind; if args.len() == 1; - if let Some(def_id) = qpath_res(cx, qpath, path.hir_id).opt_def_id(); + if let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id(); then { let lint; let msg; diff --git a/src/tools/clippy/clippy_lints/src/enum_clike.rs b/src/tools/clippy/clippy_lints/src/enum_clike.rs index fb80f48a9ccf3..ae56a8ba5ab4b 100644 --- a/src/tools/clippy/clippy_lints/src/enum_clike.rs +++ b/src/tools/clippy/clippy_lints/src/enum_clike.rs @@ -3,10 +3,9 @@ use crate::consts::{miri_to_const, Constant}; use crate::utils::span_lint; -use rustc_ast::ast::{IntTy, UintTy}; use rustc_hir::{Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty; +use rustc_middle::ty::{self, IntTy, UintTy}; use rustc_middle::ty::util::IntTypeExt; use rustc_session::{declare_lint_pass, declare_tool_lint}; use std::convert::TryFrom; diff --git a/src/tools/clippy/clippy_lints/src/exit.rs b/src/tools/clippy/clippy_lints/src/exit.rs index 7337d98c8be37..915859270009b 100644 --- a/src/tools/clippy/clippy_lints/src/exit.rs +++ b/src/tools/clippy/clippy_lints/src/exit.rs @@ -1,4 +1,4 @@ -use crate::utils::{is_entrypoint_fn, match_def_path, paths, qpath_res, span_lint}; +use crate::utils::{is_entrypoint_fn, match_def_path, paths, span_lint}; use if_chain::if_chain; use rustc_hir::{Expr, ExprKind, Item, ItemKind, Node}; use rustc_lint::{LateContext, LateLintPass}; @@ -29,7 +29,7 @@ impl<'tcx> LateLintPass<'tcx> for Exit { if_chain! { if let ExprKind::Call(ref path_expr, ref _args) = e.kind; if let ExprKind::Path(ref path) = path_expr.kind; - if let Some(def_id) = qpath_res(cx, path, path_expr.hir_id).opt_def_id(); + if let Some(def_id) = cx.qpath_res(path, path_expr.hir_id).opt_def_id(); if match_def_path(cx, def_id, &paths::EXIT); then { let parent = cx.tcx.hir().get_parent_item(e.hir_id); diff --git a/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs b/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs index 9f389c8d2f9e7..527905e375d28 100644 --- a/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs +++ b/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs @@ -1,7 +1,4 @@ -use crate::utils::paths::FROM_TRAIT; -use crate::utils::{ - is_expn_of, is_type_diagnostic_item, match_def_path, match_panic_def_id, method_chain_args, span_lint_and_then, -}; +use crate::utils::{is_expn_of, is_type_diagnostic_item, match_panic_def_id, method_chain_args, span_lint_and_then}; use if_chain::if_chain; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; @@ -59,7 +56,7 @@ impl<'tcx> LateLintPass<'tcx> for FallibleImplFrom { if_chain! { if let hir::ItemKind::Impl(impl_) = &item.kind; if let Some(impl_trait_ref) = cx.tcx.impl_trait_ref(impl_def_id); - if match_def_path(cx, impl_trait_ref.def_id, &FROM_TRAIT); + if cx.tcx.is_diagnostic_item(sym::from_trait, impl_trait_ref.def_id); then { lint_impl_body(cx, item.span, impl_.items); } diff --git a/src/tools/clippy/clippy_lints/src/float_literal.rs b/src/tools/clippy/clippy_lints/src/float_literal.rs index 1fe4461533b36..be646cbe4d043 100644 --- a/src/tools/clippy/clippy_lints/src/float_literal.rs +++ b/src/tools/clippy/clippy_lints/src/float_literal.rs @@ -1,10 +1,10 @@ use crate::utils::{numeric_literal, span_lint_and_sugg}; use if_chain::if_chain; -use rustc_ast::ast::{FloatTy, LitFloatType, LitKind}; +use rustc_ast::ast::{self, LitFloatType, LitKind}; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty; +use rustc_middle::ty::{self, FloatTy}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use std::fmt; @@ -75,8 +75,8 @@ impl<'tcx> LateLintPass<'tcx> for FloatLiteral { let digits = count_digits(&sym_str); let max = max_digits(fty); let type_suffix = match lit_float_ty { - LitFloatType::Suffixed(FloatTy::F32) => Some("f32"), - LitFloatType::Suffixed(FloatTy::F64) => Some("f64"), + LitFloatType::Suffixed(ast::FloatTy::F32) => Some("f32"), + LitFloatType::Suffixed(ast::FloatTy::F64) => Some("f64"), LitFloatType::Unsuffixed => None }; let (is_whole, mut float_str) = match fty { diff --git a/src/tools/clippy/clippy_lints/src/functions.rs b/src/tools/clippy/clippy_lints/src/functions.rs index fd93548b55c6d..8795425461033 100644 --- a/src/tools/clippy/clippy_lints/src/functions.rs +++ b/src/tools/clippy/clippy_lints/src/functions.rs @@ -1,7 +1,7 @@ use crate::utils::{ attr_by_name, attrs::is_proc_macro, is_must_use_ty, is_trait_impl_item, is_type_diagnostic_item, iter_input_pats, - last_path_segment, match_def_path, must_use_attr, qpath_res, return_ty, snippet, snippet_opt, span_lint, - span_lint_and_help, span_lint_and_then, trait_ref_of_method, type_is_unsafe_function, + last_path_segment, match_def_path, must_use_attr, return_ty, snippet, snippet_opt, span_lint, span_lint_and_help, + span_lint_and_then, trait_ref_of_method, type_is_unsafe_function, }; use if_chain::if_chain; use rustc_ast::ast::Attribute; @@ -659,7 +659,7 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for DerefVisitor<'a, 'tcx> { impl<'a, 'tcx> DerefVisitor<'a, 'tcx> { fn check_arg(&self, ptr: &hir::Expr<'_>) { if let hir::ExprKind::Path(ref qpath) = ptr.kind { - if let Res::Local(id) = qpath_res(self.cx, qpath, ptr.hir_id) { + if let Res::Local(id) = self.cx.qpath_res(qpath, ptr.hir_id) { if self.ptrs.contains(&id) { span_lint( self.cx, @@ -722,7 +722,7 @@ fn is_mutated_static(cx: &LateContext<'_>, e: &hir::Expr<'_>) -> bool { use hir::ExprKind::{Field, Index, Path}; match e.kind { - Path(ref qpath) => !matches!(qpath_res(cx, qpath, e.hir_id), Res::Local(_)), + Path(ref qpath) => !matches!(cx.qpath_res(qpath, e.hir_id), Res::Local(_)), Field(ref inner, _) | Index(ref inner, _) => is_mutated_static(cx, inner), _ => false, } diff --git a/src/tools/clippy/clippy_lints/src/let_if_seq.rs b/src/tools/clippy/clippy_lints/src/let_if_seq.rs index db717cd1240a4..5886c2360e362 100644 --- a/src/tools/clippy/clippy_lints/src/let_if_seq.rs +++ b/src/tools/clippy/clippy_lints/src/let_if_seq.rs @@ -1,4 +1,4 @@ -use crate::utils::{qpath_res, snippet, span_lint_and_then, visitors::LocalUsedVisitor}; +use crate::utils::{snippet, span_lint_and_then, visitors::LocalUsedVisitor}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; @@ -145,7 +145,7 @@ fn check_assign<'tcx>( if let hir::StmtKind::Semi(ref expr) = expr.kind; if let hir::ExprKind::Assign(ref var, ref value, _) = expr.kind; if let hir::ExprKind::Path(ref qpath) = var.kind; - if let Res::Local(local_id) = qpath_res(cx, qpath, var.hir_id); + if let Res::Local(local_id) = cx.qpath_res(qpath, var.hir_id); if decl == local_id; then { let mut v = LocalUsedVisitor::new(decl); diff --git a/src/tools/clippy/clippy_lints/src/loops.rs b/src/tools/clippy/clippy_lints/src/loops.rs index bbcea387de2cb..f89075005bc7a 100644 --- a/src/tools/clippy/clippy_lints/src/loops.rs +++ b/src/tools/clippy/clippy_lints/src/loops.rs @@ -6,9 +6,9 @@ use crate::utils::visitors::LocalUsedVisitor; use crate::utils::{ contains_name, get_enclosing_block, get_parent_expr, get_trait_def_id, has_iter_method, higher, implements_trait, indent_of, is_in_panic_handler, is_integer_const, is_no_std_crate, is_refutable, is_type_diagnostic_item, - last_path_segment, match_trait_method, match_type, match_var, multispan_sugg, qpath_res, single_segment_path, - snippet, snippet_with_applicability, snippet_with_macro_callsite, span_lint, span_lint_and_help, - span_lint_and_sugg, span_lint_and_then, sugg, SpanlessEq, + last_path_segment, match_trait_method, match_type, match_var, multispan_sugg, single_segment_path, snippet, + snippet_with_applicability, snippet_with_macro_callsite, span_lint, span_lint_and_help, span_lint_and_sugg, + span_lint_and_then, sugg, SpanlessEq, }; use if_chain::if_chain; use rustc_ast::ast; @@ -848,7 +848,7 @@ fn same_var<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, var: HirId) -> bool { if let ExprKind::Path(qpath) = &expr.kind; if let QPath::Resolved(None, path) = qpath; if path.segments.len() == 1; - if let Res::Local(local_id) = qpath_res(cx, qpath, expr.hir_id); + if let Res::Local(local_id) = cx.qpath_res(qpath, expr.hir_id); then { // our variable! local_id == var @@ -1420,7 +1420,7 @@ fn detect_same_item_push<'tcx>( // Make sure that the push does not involve possibly mutating values match pushed_item.kind { ExprKind::Path(ref qpath) => { - match qpath_res(cx, qpath, pushed_item.hir_id) { + match cx.qpath_res(qpath, pushed_item.hir_id) { // immutable bindings that are initialized with literal or constant Res::Local(hir_id) => { if_chain! { @@ -1437,7 +1437,7 @@ fn detect_same_item_push<'tcx>( ExprKind::Lit(..) => emit_lint(cx, vec, pushed_item), // immutable bindings that are initialized with constant ExprKind::Path(ref path) => { - if let Res::Def(DefKind::Const, ..) = qpath_res(cx, path, init.hir_id) { + if let Res::Def(DefKind::Const, ..) = cx.qpath_res(path, init.hir_id) { emit_lint(cx, vec, pushed_item); } } @@ -2028,7 +2028,7 @@ fn check_for_mutability(cx: &LateContext<'_>, bound: &Expr<'_>) -> Option if let ExprKind::Path(ref qpath) = bound.kind; if let QPath::Resolved(None, _) = *qpath; then { - let res = qpath_res(cx, qpath, bound.hir_id); + let res = cx.qpath_res(qpath, bound.hir_id); if let Res::Local(hir_id) = res { let node_str = cx.tcx.hir().get(hir_id); if_chain! { @@ -2120,7 +2120,7 @@ impl<'a, 'tcx> VarVisitor<'a, 'tcx> { if self.prefer_mutable { self.indexed_mut.insert(seqvar.segments[0].ident.name); } - let res = qpath_res(self.cx, seqpath, seqexpr.hir_id); + let res = self.cx.qpath_res(seqpath, seqexpr.hir_id); match res { Res::Local(hir_id) => { let parent_id = self.cx.tcx.hir().get_parent_item(expr.hir_id); @@ -2184,7 +2184,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> { if let QPath::Resolved(None, ref path) = *qpath; if path.segments.len() == 1; then { - if let Res::Local(local_id) = qpath_res(self.cx, qpath, expr.hir_id) { + if let Res::Local(local_id) = self.cx.qpath_res(qpath, expr.hir_id) { if local_id == self.var { self.nonindex = true; } else { @@ -2589,7 +2589,7 @@ impl<'a, 'tcx> Visitor<'tcx> for InitializeVisitor<'a, 'tcx> { fn var_def_id(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option { if let ExprKind::Path(ref qpath) = expr.kind { - let path_res = qpath_res(cx, qpath, expr.hir_id); + let path_res = cx.qpath_res(qpath, expr.hir_id); if let Res::Local(hir_id) = path_res { return Some(hir_id); } @@ -2819,7 +2819,7 @@ impl<'a, 'tcx> VarCollectorVisitor<'a, 'tcx> { if_chain! { if let ExprKind::Path(ref qpath) = ex.kind; if let QPath::Resolved(None, _) = *qpath; - let res = qpath_res(self.cx, qpath, ex.hir_id); + let res = self.cx.qpath_res(qpath, ex.hir_id); then { match res { Res::Local(hir_id) => { diff --git a/src/tools/clippy/clippy_lints/src/manual_strip.rs b/src/tools/clippy/clippy_lints/src/manual_strip.rs index a0cfe145a301c..42a92104a4919 100644 --- a/src/tools/clippy/clippy_lints/src/manual_strip.rs +++ b/src/tools/clippy/clippy_lints/src/manual_strip.rs @@ -1,7 +1,7 @@ use crate::consts::{constant, Constant}; use crate::utils::usage::mutated_variables; use crate::utils::{ - eq_expr_value, higher, match_def_path, meets_msrv, multispan_sugg, paths, qpath_res, snippet, span_lint_and_then, + eq_expr_value, higher, match_def_path, meets_msrv, multispan_sugg, paths, snippet, span_lint_and_then, }; use if_chain::if_chain; @@ -92,7 +92,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualStrip { } else { return; }; - let target_res = qpath_res(cx, &target_path, target_arg.hir_id); + let target_res = cx.qpath_res(&target_path, target_arg.hir_id); if target_res == Res::Err { return; }; @@ -221,7 +221,7 @@ fn find_stripping<'tcx>( if let ExprKind::Index(indexed, index) = &unref.kind; if let Some(higher::Range { start, end, .. }) = higher::range(index); if let ExprKind::Path(path) = &indexed.kind; - if qpath_res(self.cx, path, ex.hir_id) == self.target; + if self.cx.qpath_res(path, ex.hir_id) == self.target; then { match (self.strip_kind, start, end) { (StripKind::Prefix, Some(start), None) => { @@ -235,7 +235,7 @@ fn find_stripping<'tcx>( if let ExprKind::Binary(Spanned { node: BinOpKind::Sub, .. }, left, right) = end.kind; if let Some(left_arg) = len_arg(self.cx, left); if let ExprKind::Path(left_path) = &left_arg.kind; - if qpath_res(self.cx, left_path, left_arg.hir_id) == self.target; + if self.cx.qpath_res(left_path, left_arg.hir_id) == self.target; if eq_pattern_length(self.cx, self.pattern, right); then { self.results.push(ex.span); diff --git a/src/tools/clippy/clippy_lints/src/mem_forget.rs b/src/tools/clippy/clippy_lints/src/mem_forget.rs index 8c6fd10f98a1e..d34f9761e26f9 100644 --- a/src/tools/clippy/clippy_lints/src/mem_forget.rs +++ b/src/tools/clippy/clippy_lints/src/mem_forget.rs @@ -1,4 +1,4 @@ -use crate::utils::{match_def_path, paths, qpath_res, span_lint}; +use crate::utils::{match_def_path, paths, span_lint}; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -29,7 +29,7 @@ impl<'tcx> LateLintPass<'tcx> for MemForget { fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { if let ExprKind::Call(ref path_expr, ref args) = e.kind { if let ExprKind::Path(ref qpath) = path_expr.kind { - if let Some(def_id) = qpath_res(cx, qpath, path_expr.hir_id).opt_def_id() { + if let Some(def_id) = cx.qpath_res(qpath, path_expr.hir_id).opt_def_id() { if match_def_path(cx, def_id, &paths::MEM_FORGET) { let forgot_ty = cx.typeck_results().expr_ty(&args[0]); diff --git a/src/tools/clippy/clippy_lints/src/mutex_atomic.rs b/src/tools/clippy/clippy_lints/src/mutex_atomic.rs index ea986874291e0..40b236493a313 100644 --- a/src/tools/clippy/clippy_lints/src/mutex_atomic.rs +++ b/src/tools/clippy/clippy_lints/src/mutex_atomic.rs @@ -3,7 +3,6 @@ //! This lint is **warn** by default use crate::utils::{is_type_diagnostic_item, span_lint}; -use rustc_ast::ast; use rustc_hir::Expr; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{self, Ty}; @@ -77,8 +76,8 @@ impl<'tcx> LateLintPass<'tcx> for Mutex { atomic_name ); match *mutex_param.kind() { - ty::Uint(t) if t != ast::UintTy::Usize => span_lint(cx, MUTEX_INTEGER, expr.span, &msg), - ty::Int(t) if t != ast::IntTy::Isize => span_lint(cx, MUTEX_INTEGER, expr.span, &msg), + ty::Uint(t) if t != ty::UintTy::Usize => span_lint(cx, MUTEX_INTEGER, expr.span, &msg), + ty::Int(t) if t != ty::IntTy::Isize => span_lint(cx, MUTEX_INTEGER, expr.span, &msg), _ => span_lint(cx, MUTEX_ATOMIC, expr.span, &msg), }; } diff --git a/src/tools/clippy/clippy_lints/src/no_effect.rs b/src/tools/clippy/clippy_lints/src/no_effect.rs index b1b5b3439a0e3..69302d695ce0a 100644 --- a/src/tools/clippy/clippy_lints/src/no_effect.rs +++ b/src/tools/clippy/clippy_lints/src/no_effect.rs @@ -1,4 +1,4 @@ -use crate::utils::{has_drop, qpath_res, snippet_opt, span_lint, span_lint_and_sugg}; +use crate::utils::{has_drop, snippet_opt, span_lint, span_lint_and_sugg}; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; use rustc_hir::{BinOpKind, BlockCheckMode, Expr, ExprKind, Stmt, StmtKind, UnsafeSource}; @@ -67,7 +67,7 @@ fn has_no_effect(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { }, ExprKind::Call(ref callee, ref args) => { if let ExprKind::Path(ref qpath) = callee.kind { - let res = qpath_res(cx, qpath, callee.hir_id); + let res = cx.qpath_res(qpath, callee.hir_id); match res { Res::Def(DefKind::Struct | DefKind::Variant | DefKind::Ctor(..), ..) => { !has_drop(cx, cx.typeck_results().expr_ty(expr)) @@ -146,7 +146,7 @@ fn reduce_expression<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option { if let ExprKind::Path(ref qpath) = callee.kind { - let res = qpath_res(cx, qpath, callee.hir_id); + let res = cx.qpath_res(qpath, callee.hir_id); match res { Res::Def(DefKind::Struct | DefKind::Variant | DefKind::Ctor(..), ..) if !has_drop(cx, cx.typeck_results().expr_ty(expr)) => diff --git a/src/tools/clippy/clippy_lints/src/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs index 3a9aa6ced03ba..f57d753631755 100644 --- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs +++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs @@ -18,7 +18,7 @@ use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::{InnerSpan, Span, DUMMY_SP}; use rustc_typeck::hir_ty_to_ty; -use crate::utils::{in_constant, qpath_res, span_lint_and_then}; +use crate::utils::{in_constant, span_lint_and_then}; use if_chain::if_chain; // FIXME: this is a correctness problem but there's no suitable @@ -339,7 +339,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst { } // Make sure it is a const item. - let item_def_id = match qpath_res(cx, qpath, expr.hir_id) { + let item_def_id = match cx.qpath_res(qpath, expr.hir_id) { Res::Def(DefKind::Const | DefKind::AssocConst, did) => did, _ => return, }; diff --git a/src/tools/clippy/clippy_lints/src/to_string_in_display.rs b/src/tools/clippy/clippy_lints/src/to_string_in_display.rs index c53727ba16004..fa508df865e48 100644 --- a/src/tools/clippy/clippy_lints/src/to_string_in_display.rs +++ b/src/tools/clippy/clippy_lints/src/to_string_in_display.rs @@ -1,4 +1,4 @@ -use crate::utils::{match_def_path, match_trait_method, paths, qpath_res, span_lint}; +use crate::utils::{match_def_path, match_trait_method, paths, span_lint}; use if_chain::if_chain; use rustc_hir::def::Res; use rustc_hir::{Expr, ExprKind, HirId, Impl, ImplItem, ImplItemKind, Item, ItemKind}; @@ -94,7 +94,7 @@ impl LateLintPass<'_> for ToStringInDisplay { if match_trait_method(cx, expr, &paths::TO_STRING); if self.in_display_impl; if let ExprKind::Path(ref qpath) = args[0].kind; - if let Res::Local(hir_id) = qpath_res(cx, qpath, args[0].hir_id); + if let Res::Local(hir_id) = cx.qpath_res(qpath, args[0].hir_id); if let Some(self_hir_id) = self.self_hir_id; if hir_id == self_hir_id; then { diff --git a/src/tools/clippy/clippy_lints/src/transmute.rs b/src/tools/clippy/clippy_lints/src/transmute.rs index b0909f7317740..d977cea4da50b 100644 --- a/src/tools/clippy/clippy_lints/src/transmute.rs +++ b/src/tools/clippy/clippy_lints/src/transmute.rs @@ -443,7 +443,7 @@ impl<'tcx> LateLintPass<'tcx> for Transmute { ); }, ), - (ty::Int(ast::IntTy::I32) | ty::Uint(ast::UintTy::U32), &ty::Char) => { + (ty::Int(ty::IntTy::I32) | ty::Uint(ty::UintTy::U32), &ty::Char) => { span_lint_and_then( cx, TRANSMUTE_INT_TO_CHAR, @@ -468,7 +468,7 @@ impl<'tcx> LateLintPass<'tcx> for Transmute { (ty::Ref(_, ty_from, from_mutbl), ty::Ref(_, ty_to, to_mutbl)) => { if_chain! { if let (&ty::Slice(slice_ty), &ty::Str) = (&ty_from.kind(), &ty_to.kind()); - if let ty::Uint(ast::UintTy::U8) = slice_ty.kind(); + if let ty::Uint(ty::UintTy::U8) = slice_ty.kind(); if from_mutbl == to_mutbl; then { let postfix = if *from_mutbl == Mutability::Mut { @@ -536,7 +536,7 @@ impl<'tcx> LateLintPass<'tcx> for Transmute { } }, ), - (ty::Int(ast::IntTy::I8) | ty::Uint(ast::UintTy::U8), ty::Bool) => { + (ty::Int(ty::IntTy::I8) | ty::Uint(ty::UintTy::U8), ty::Bool) => { span_lint_and_then( cx, TRANSMUTE_INT_TO_BOOL, diff --git a/src/tools/clippy/clippy_lints/src/types.rs b/src/tools/clippy/clippy_lints/src/types.rs index 3b5a83d2a0bec..04c32ce9e8f2c 100644 --- a/src/tools/clippy/clippy_lints/src/types.rs +++ b/src/tools/clippy/clippy_lints/src/types.rs @@ -5,7 +5,7 @@ use std::cmp::Ordering; use std::collections::BTreeMap; use if_chain::if_chain; -use rustc_ast::{FloatTy, IntTy, LitFloatType, LitIntType, LitKind, UintTy}; +use rustc_ast::{LitFloatType, LitIntType, LitKind}; use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::intravisit::{walk_body, walk_expr, walk_ty, FnKind, NestedVisitorMap, Visitor}; @@ -18,7 +18,7 @@ use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::hir::map::Map; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::TypeFoldable; -use rustc_middle::ty::{self, InferTy, Ty, TyCtxt, TyS, TypeAndMut, TypeckResults}; +use rustc_middle::ty::{self, FloatTy, InferTy, IntTy, Ty, TyCtxt, TyS, TypeAndMut, TypeckResults, UintTy}; use rustc_semver::RustcVersion; use rustc_session::{declare_lint_pass, declare_tool_lint, impl_lint_pass}; use rustc_span::hygiene::{ExpnKind, MacroKind}; @@ -34,7 +34,7 @@ use crate::utils::sugg::Sugg; use crate::utils::{ clip, comparisons, differing_macro_contexts, higher, in_constant, indent_of, int_bits, is_hir_ty_cfg_dependant, is_type_diagnostic_item, last_path_segment, match_def_path, match_path, meets_msrv, method_chain_args, - multispan_sugg, numeric_literal::NumericLiteral, qpath_res, reindent_multiline, sext, snippet, snippet_opt, + multispan_sugg, numeric_literal::NumericLiteral, reindent_multiline, sext, snippet, snippet_opt, snippet_with_applicability, snippet_with_macro_callsite, span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then, unsext, }; @@ -298,7 +298,7 @@ fn match_type_parameter(cx: &LateContext<'_>, qpath: &QPath<'_>, path: &[&str]) _ => None, }); if let TyKind::Path(ref qpath) = ty.kind; - if let Some(did) = qpath_res(cx, qpath, ty.hir_id).opt_def_id(); + if let Some(did) = cx.qpath_res(qpath, ty.hir_id).opt_def_id(); if match_def_path(cx, did, path); then { return Some(ty.span); @@ -365,7 +365,7 @@ impl Types { match hir_ty.kind { TyKind::Path(ref qpath) if !is_local => { let hir_id = hir_ty.hir_id; - let res = qpath_res(cx, qpath, hir_id); + let res = cx.qpath_res(qpath, hir_id); if let Some(def_id) = res.opt_def_id() { if Some(def_id) == cx.tcx.lang_items().owned_box() { if let Some(span) = match_borrows_parameter(cx, qpath) { @@ -535,7 +535,7 @@ impl Types { }); // ty is now _ at this point if let TyKind::Path(ref ty_qpath) = ty.kind; - let res = qpath_res(cx, ty_qpath, ty.hir_id); + let res = cx.qpath_res(ty_qpath, ty.hir_id); if let Some(def_id) = res.opt_def_id(); if Some(def_id) == cx.tcx.lang_items().owned_box(); // At this point, we know ty is Box, now get T @@ -652,7 +652,7 @@ impl Types { match mut_ty.ty.kind { TyKind::Path(ref qpath) => { let hir_id = mut_ty.ty.hir_id; - let def = qpath_res(cx, qpath, hir_id); + let def = cx.qpath_res(qpath, hir_id); if_chain! { if let Some(def_id) = def.opt_def_id(); if Some(def_id) == cx.tcx.lang_items().owned_box(); @@ -739,7 +739,7 @@ fn is_any_trait(t: &hir::Ty<'_>) -> bool { fn get_bounds_if_impl_trait<'tcx>(cx: &LateContext<'tcx>, qpath: &QPath<'_>, id: HirId) -> Option> { if_chain! { - if let Some(did) = qpath_res(cx, qpath, id).opt_def_id(); + if let Some(did) = cx.qpath_res(qpath, id).opt_def_id(); if let Some(Node::GenericParam(generic_param)) = cx.tcx.hir().get_if_local(did); if let GenericParamKind::Type { synthetic, .. } = generic_param.kind; if synthetic == Some(SyntheticTyParamKind::ImplTrait); @@ -1106,9 +1106,7 @@ fn is_empty_block(expr: &Expr<'_>) -> bool { expr.kind, ExprKind::Block( Block { - stmts: &[], - expr: None, - .. + stmts: &[], expr: None, .. }, _, ) diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs index 7aa17520ba79f..822863ca3e279 100644 --- a/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs +++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs @@ -1,7 +1,7 @@ use crate::consts::{constant_simple, Constant}; use crate::utils::{ - is_expn_of, match_def_path, match_qpath, match_type, method_calls, path_to_res, paths, qpath_res, run_lints, - snippet, span_lint, span_lint_and_help, span_lint_and_sugg, SpanlessEq, + is_expn_of, match_def_path, match_qpath, match_type, method_calls, path_to_res, paths, run_lints, snippet, + span_lint, span_lint_and_help, span_lint_and_sugg, SpanlessEq, }; use if_chain::if_chain; use rustc_ast::ast::{Crate as AstCrate, ItemKind, LitKind, NodeId}; @@ -787,7 +787,7 @@ fn path_to_matched_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option return path_to_matched_type(cx, expr), - ExprKind::Path(qpath) => match qpath_res(cx, qpath, expr.hir_id) { + ExprKind::Path(qpath) => match cx.qpath_res(qpath, expr.hir_id) { Res::Local(hir_id) => { let parent_id = cx.tcx.hir().get_parent_node(hir_id); if let Some(Node::Local(local)) = cx.tcx.hir().find(parent_id) { diff --git a/src/tools/clippy/clippy_lints/src/utils/mod.rs b/src/tools/clippy/clippy_lints/src/utils/mod.rs index 9b262517a9834..0bbb6a52a2046 100644 --- a/src/tools/clippy/clippy_lints/src/utils/mod.rs +++ b/src/tools/clippy/clippy_lints/src/utils/mod.rs @@ -35,7 +35,6 @@ use std::mem; use if_chain::if_chain; use rustc_ast::ast::{self, Attribute, LitKind}; -use rustc_attr as attr; use rustc_data_structures::fx::FxHashMap; use rustc_errors::Applicability; use rustc_hir as hir; @@ -370,19 +369,6 @@ pub fn path_to_res(cx: &LateContext<'_>, path: &[&str]) -> Option { } } -pub fn qpath_res(cx: &LateContext<'_>, qpath: &hir::QPath<'_>, id: hir::HirId) -> Res { - match qpath { - hir::QPath::Resolved(_, path) => path.res, - hir::QPath::TypeRelative(..) | hir::QPath::LangItem(..) => { - if cx.tcx.has_typeck_results(id.owner.to_def_id()) { - cx.tcx.typeck(id.owner).qpath_res(qpath, id) - } else { - Res::Err - } - }, - } -} - /// Convenience function to get the `DefId` of a trait by path. /// It could be a trait or trait alias. pub fn get_trait_def_id(cx: &LateContext<'_>, path: &[&str]) -> Option { @@ -1224,27 +1210,27 @@ pub fn get_arg_name(pat: &Pat<'_>) -> Option { } } -pub fn int_bits(tcx: TyCtxt<'_>, ity: ast::IntTy) -> u64 { - Integer::from_attr(&tcx, attr::IntType::SignedInt(ity)).size().bits() +pub fn int_bits(tcx: TyCtxt<'_>, ity: ty::IntTy) -> u64 { + Integer::from_int_ty(&tcx, ity).size().bits() } #[allow(clippy::cast_possible_wrap)] /// Turn a constant int byte representation into an i128 -pub fn sext(tcx: TyCtxt<'_>, u: u128, ity: ast::IntTy) -> i128 { +pub fn sext(tcx: TyCtxt<'_>, u: u128, ity: ty::IntTy) -> i128 { let amt = 128 - int_bits(tcx, ity); ((u as i128) << amt) >> amt } #[allow(clippy::cast_sign_loss)] /// clip unused bytes -pub fn unsext(tcx: TyCtxt<'_>, u: i128, ity: ast::IntTy) -> u128 { +pub fn unsext(tcx: TyCtxt<'_>, u: i128, ity: ty::IntTy) -> u128 { let amt = 128 - int_bits(tcx, ity); ((u as u128) << amt) >> amt } /// clip unused bytes -pub fn clip(tcx: TyCtxt<'_>, u: u128, ity: ast::UintTy) -> u128 { - let bits = Integer::from_attr(&tcx, attr::IntType::UnsignedInt(ity)).size().bits(); +pub fn clip(tcx: TyCtxt<'_>, u: u128, ity: ty::UintTy) -> u128 { + let bits = Integer::from_uint_ty(&tcx, ity).size().bits(); let amt = 128 - bits; (u << amt) >> amt } diff --git a/src/tools/clippy/clippy_lints/src/utils/paths.rs b/src/tools/clippy/clippy_lints/src/utils/paths.rs index c0b203b5388dc..432cc5b59f684 100644 --- a/src/tools/clippy/clippy_lints/src/utils/paths.rs +++ b/src/tools/clippy/clippy_lints/src/utils/paths.rs @@ -48,7 +48,6 @@ pub const FN_MUT: [&str; 3] = ["core", "ops", "FnMut"]; pub const FN_ONCE: [&str; 3] = ["core", "ops", "FnOnce"]; pub const FROM_FROM: [&str; 4] = ["core", "convert", "From", "from"]; pub const FROM_ITERATOR: [&str; 5] = ["core", "iter", "traits", "collect", "FromIterator"]; -pub const FROM_TRAIT: [&str; 3] = ["core", "convert", "From"]; pub const FUTURE_FROM_GENERATOR: [&str; 3] = ["core", "future", "from_generator"]; pub const HASH: [&str; 3] = ["core", "hash", "Hash"]; pub const HASHMAP: [&str; 5] = ["std", "collections", "hash", "map", "HashMap"];