mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
thread through a HirId to emit lints in the right place
Previously the lint would be reported at the right span, but could not be `allow`ed or `expect`ed in that location, because the lint was actually emitted using `CRATE_HIR_ID`
This commit is contained in:
@@ -346,7 +346,7 @@ fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
|
||||
match infer {
|
||||
ty::TyVar(_) => self.next_ty_var(DUMMY_SP),
|
||||
ty::IntVar(_) => self.next_int_var(),
|
||||
ty::FloatVar(_) => self.next_float_var(DUMMY_SP),
|
||||
ty::FloatVar(_) => self.next_float_var(DUMMY_SP, None),
|
||||
ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => {
|
||||
bug!("unexpected fresh ty outside of the trait solver")
|
||||
}
|
||||
|
||||
@@ -349,7 +349,7 @@ fn check_expr_kind(
|
||||
|
||||
let tcx = self.tcx;
|
||||
match expr.kind {
|
||||
ExprKind::Lit(ref lit) => self.check_expr_lit(lit, expected),
|
||||
ExprKind::Lit(ref lit) => self.check_expr_lit(lit, expr.hir_id, expected),
|
||||
ExprKind::Binary(op, lhs, rhs) => self.check_expr_binop(expr, op, lhs, rhs, expected),
|
||||
ExprKind::Assign(lhs, rhs, span) => {
|
||||
self.check_expr_assign(expr, expected, lhs, rhs, span)
|
||||
|
||||
@@ -161,15 +161,15 @@ fn calculate_fallback_to_f32(&self, unresolved_variables: &[Ty<'tcx>]) -> UnordS
|
||||
.flat_map(|ty| ty.float_vid())
|
||||
.filter(|vid| roots.contains(&self.root_float_var(*vid)))
|
||||
.inspect(|vid| {
|
||||
let span = self.float_var_origin(*vid);
|
||||
let origin = self.float_var_origin(*vid);
|
||||
// Show the entire literal in the suggestion to make it clearer.
|
||||
let literal = self.tcx.sess.source_map().span_to_snippet(span).ok();
|
||||
let literal = self.tcx.sess.source_map().span_to_snippet(origin.span).ok();
|
||||
self.tcx.emit_node_span_lint(
|
||||
FLOAT_LITERAL_F32_FALLBACK,
|
||||
CRATE_HIR_ID,
|
||||
span,
|
||||
origin.lint_id.unwrap_or(CRATE_HIR_ID),
|
||||
origin.span,
|
||||
errors::FloatLiteralF32Fallback {
|
||||
span: literal.as_ref().map(|_| span),
|
||||
span: literal.as_ref().map(|_| origin.span),
|
||||
literal: literal.unwrap_or_default(),
|
||||
},
|
||||
);
|
||||
|
||||
@@ -718,6 +718,7 @@ fn suggest_ptr_null_mut(
|
||||
pub(in super::super) fn check_expr_lit(
|
||||
&self,
|
||||
lit: &hir::Lit,
|
||||
lint_id: HirId,
|
||||
expected: Expectation<'tcx>,
|
||||
) -> Ty<'tcx> {
|
||||
let tcx = self.tcx;
|
||||
@@ -765,7 +766,7 @@ pub(in super::super) fn check_expr_lit(
|
||||
ty::Float(_) => Some(ty),
|
||||
_ => None,
|
||||
});
|
||||
opt_ty.unwrap_or_else(|| self.next_float_var(lit.span))
|
||||
opt_ty.unwrap_or_else(|| self.next_float_var(lit.span, Some(lint_id)))
|
||||
}
|
||||
ast::LitKind::Bool(_) => tcx.types.bool,
|
||||
ast::LitKind::CStr(_, _) => Ty::new_imm_ref(
|
||||
|
||||
@@ -917,7 +917,7 @@ fn should_peel_smart_pointer(&self, peel_kind: PeelKind, expected: Ty<'tcx>) ->
|
||||
fn check_pat_expr_unadjusted(&self, lt: &'tcx hir::PatExpr<'tcx>) -> Ty<'tcx> {
|
||||
let ty = match <.kind {
|
||||
rustc_hir::PatExprKind::Lit { lit, negated } => {
|
||||
let ty = self.check_expr_lit(lit, Expectation::NoExpectation);
|
||||
let ty = self.check_expr_lit(lit, lt.hir_id, Expectation::NoExpectation);
|
||||
if *negated {
|
||||
self.register_bound(
|
||||
ty,
|
||||
|
||||
@@ -107,7 +107,10 @@ pub fn instantiate_canonical_var(
|
||||
|
||||
CanonicalVarKind::Int => self.next_int_var().into(),
|
||||
|
||||
CanonicalVarKind::Float => self.next_float_var(span).into(),
|
||||
CanonicalVarKind::Float => {
|
||||
// There is no HirId available to pass as a lint_id.
|
||||
self.next_float_var(span, None).into()
|
||||
}
|
||||
|
||||
CanonicalVarKind::PlaceholderTy(ty::PlaceholderType { universe, bound, .. }) => {
|
||||
let universe_mapped = universe_map(universe);
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
use rustc_data_structures::undo_log::{Rollback, UndoLogs};
|
||||
use rustc_data_structures::unify as ut;
|
||||
use rustc_errors::{DiagCtxtHandle, ErrorGuaranteed};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_hir::{self as hir, HirId};
|
||||
use rustc_index::IndexVec;
|
||||
use rustc_macros::extension;
|
||||
pub use rustc_macros::{TypeFoldable, TypeVisitable};
|
||||
@@ -39,6 +39,7 @@
|
||||
use type_variable::TypeVariableOrigin;
|
||||
|
||||
use crate::infer::snapshot::undo_log::UndoLog;
|
||||
use crate::infer::type_variable::FloatVariableOrigin;
|
||||
use crate::infer::unify_key::{ConstVariableOrigin, ConstVariableValue, ConstVidKey};
|
||||
use crate::traits::{
|
||||
self, ObligationCause, ObligationInspector, PredicateObligation, PredicateObligations,
|
||||
@@ -109,9 +110,10 @@ pub struct InferCtxtInner<'tcx> {
|
||||
/// Map from floating variable to the kind of float it represents.
|
||||
float_unification_storage: ut::UnificationTableStorage<ty::FloatVid>,
|
||||
|
||||
/// Map from floating variable to the origin span it came from. This is only used for the FCW
|
||||
/// for the fallback to `f32`, so can be removed once the `f32` fallback is removed.
|
||||
float_origin_span_storage: IndexVec<FloatVid, Span>,
|
||||
/// Map from floating variable to the origin span it came from, and the HirId that should be
|
||||
/// used to lint at that location. This is only used for the FCW for the fallback to `f32`,
|
||||
/// so can be removed once the `f32` fallback is removed.
|
||||
float_origin_origin_storage: IndexVec<FloatVid, FloatVariableOrigin>,
|
||||
|
||||
/// Tracks the set of region variables and the constraints between them.
|
||||
///
|
||||
@@ -166,7 +168,7 @@ fn new() -> InferCtxtInner<'tcx> {
|
||||
const_unification_storage: Default::default(),
|
||||
int_unification_storage: Default::default(),
|
||||
float_unification_storage: Default::default(),
|
||||
float_origin_span_storage: Default::default(),
|
||||
float_origin_origin_storage: Default::default(),
|
||||
region_constraint_storage: Some(Default::default()),
|
||||
region_obligations: Default::default(),
|
||||
region_assumptions: Default::default(),
|
||||
@@ -653,8 +655,8 @@ pub fn type_var_origin(&self, vid: TyVid) -> TypeVariableOrigin {
|
||||
/// Returns the origin of the float type variable identified by `vid`.
|
||||
///
|
||||
/// No attempt is made to resolve `vid` to its root variable.
|
||||
pub fn float_var_origin(&self, vid: FloatVid) -> Span {
|
||||
self.inner.borrow_mut().float_origin_span_storage[vid]
|
||||
pub fn float_var_origin(&self, vid: FloatVid) -> FloatVariableOrigin {
|
||||
self.inner.borrow_mut().float_origin_origin_storage[vid]
|
||||
}
|
||||
|
||||
/// Returns the origin of the const variable identified by `vid`
|
||||
@@ -834,10 +836,11 @@ pub fn next_int_var(&self) -> Ty<'tcx> {
|
||||
Ty::new_int_var(self.tcx, next_int_var_id)
|
||||
}
|
||||
|
||||
pub fn next_float_var(&self, span: Span) -> Ty<'tcx> {
|
||||
pub fn next_float_var(&self, span: Span, lint_id: Option<HirId>) -> Ty<'tcx> {
|
||||
let mut inner = self.inner.borrow_mut();
|
||||
let next_float_var_id = inner.float_unification_table().new_key(ty::FloatVarValue::Unknown);
|
||||
let span_index = inner.float_origin_span_storage.push(span);
|
||||
let origin = FloatVariableOrigin { span, lint_id };
|
||||
let span_index = inner.float_origin_origin_storage.push(origin);
|
||||
debug_assert_eq!(next_float_var_id, span_index);
|
||||
Ty::new_float_var(self.tcx, next_float_var_id)
|
||||
}
|
||||
|
||||
@@ -6,12 +6,11 @@
|
||||
self, ConstVid, FloatVid, IntVid, RegionVid, Ty, TyCtxt, TyVid, TypeFoldable, TypeFolder,
|
||||
TypeSuperFoldable, TypeVisitableExt,
|
||||
};
|
||||
use rustc_span::Span;
|
||||
use tracing::instrument;
|
||||
use ut::UnifyKey;
|
||||
|
||||
use super::VariableLengths;
|
||||
use crate::infer::type_variable::TypeVariableOrigin;
|
||||
use crate::infer::type_variable::{FloatVariableOrigin, TypeVariableOrigin};
|
||||
use crate::infer::unify_key::{ConstVariableValue, ConstVidKey};
|
||||
use crate::infer::{
|
||||
ConstVariableOrigin, InferCtxt, InferCtxtInner, RegionVariableOrigin, UnificationTable,
|
||||
@@ -31,9 +30,9 @@ fn vars_since_snapshot<'tcx, T>(
|
||||
fn float_vars_since_snapshot(
|
||||
inner: &mut InferCtxtInner<'_>,
|
||||
snapshot_var_len: usize,
|
||||
) -> (Range<FloatVid>, Vec<Span>) {
|
||||
) -> (Range<FloatVid>, Vec<FloatVariableOrigin>) {
|
||||
let range = vars_since_snapshot(&inner.float_unification_table(), snapshot_var_len);
|
||||
(range.clone(), range.map(|index| inner.float_origin_span_storage[index]).collect())
|
||||
(range.clone(), range.map(|index| inner.float_origin_origin_storage[index]).collect())
|
||||
}
|
||||
|
||||
fn const_vars_since_snapshot<'tcx>(
|
||||
@@ -141,7 +140,7 @@ struct SnapshotVarData<'tcx> {
|
||||
region_vars: (Range<RegionVid>, Vec<RegionVariableOrigin<'tcx>>),
|
||||
type_vars: (Range<TyVid>, Vec<TypeVariableOrigin>),
|
||||
int_vars: Range<IntVid>,
|
||||
float_vars: (Range<FloatVid>, Vec<Span>),
|
||||
float_vars: (Range<FloatVid>, Vec<FloatVariableOrigin>),
|
||||
const_vars: (Range<ConstVid>, Vec<ConstVariableOrigin>),
|
||||
}
|
||||
|
||||
@@ -215,8 +214,9 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
ty::FloatVar(vid) => {
|
||||
if self.snapshot_vars.float_vars.0.contains(&vid) {
|
||||
let idx = vid.as_usize() - self.snapshot_vars.float_vars.0.start.as_usize();
|
||||
let span = self.snapshot_vars.float_vars.1[idx];
|
||||
self.infcx.next_float_var(span)
|
||||
let FloatVariableOrigin { span, lint_id } =
|
||||
self.snapshot_vars.float_vars.1[idx];
|
||||
self.infcx.next_float_var(span, lint_id)
|
||||
} else {
|
||||
ty
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
use rustc_data_structures::undo_log::Rollback;
|
||||
use rustc_data_structures::{snapshot_vec as sv, unify as ut};
|
||||
use rustc_hir::HirId;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_index::IndexVec;
|
||||
use rustc_middle::bug;
|
||||
@@ -99,6 +100,16 @@ pub struct TypeVariableOrigin {
|
||||
pub param_def_id: Option<DefId>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct FloatVariableOrigin {
|
||||
pub span: Span,
|
||||
|
||||
/// `HirId` to lint at for this float variable, if any.
|
||||
///
|
||||
/// This should only be used for diagnostics.
|
||||
pub lint_id: Option<HirId>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct TypeVariableData {
|
||||
origin: TypeVariableOrigin,
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
EXPLICIT_BUILTIN_CFGS_IN_FLAGS,
|
||||
EXPORTED_PRIVATE_DEPENDENCIES,
|
||||
FFI_UNWIND_CALLS,
|
||||
FLOAT_LITERAL_F32_FALLBACK,
|
||||
FORBIDDEN_LINT_GROUPS,
|
||||
FUNCTION_ITEM_REFERENCES,
|
||||
FUZZY_PROVENANCE_CASTS,
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
//@ build-pass
|
||||
#![feature(f16, f32_from_f16)]
|
||||
#![allow(unused)]
|
||||
|
||||
// Check that float conversions work, specifically a {float} literal that normally would fall back
|
||||
// to an f64 but due to the Into bound here falls back to f32. Also test that the lint is emitted in
|
||||
// the correct location, and can be `expect`ed or `allow`ed.
|
||||
fn convert(x: impl Into<f32>) -> f32 {
|
||||
x.into()
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let _ = convert(1.0f32);
|
||||
let _ = convert(1.0f16);
|
||||
#[expect(float_literal_f32_fallback)]
|
||||
let _ = convert(1.0);
|
||||
}
|
||||
@@ -6,7 +6,7 @@ LL | foo(1.0);
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #154024 <https://github.com/rust-lang/rust/issues/154024>
|
||||
= note: `#[warn(float_literal_f32_fallback)]` on by default
|
||||
= note: `#[warn(float_literal_f32_fallback)]` (part of `#[warn(future_incompatible)]`) on by default
|
||||
|
||||
warning: falling back to `f32` as the trait bound `f32: From<f64>` is not satisfied
|
||||
--> $DIR/f32-into-f32.rs:12:11
|
||||
|
||||
@@ -6,7 +6,7 @@ LL | foo(1.0);
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #154024 <https://github.com/rust-lang/rust/issues/154024>
|
||||
= note: `#[warn(float_literal_f32_fallback)]` on by default
|
||||
= note: `#[warn(float_literal_f32_fallback)]` (part of `#[warn(future_incompatible)]`) on by default
|
||||
|
||||
warning: falling back to `f32` as the trait bound `f32: From<f64>` is not satisfied
|
||||
--> $DIR/f32-into-f32.rs:12:11
|
||||
|
||||
@@ -6,7 +6,7 @@ LL | let x = f32::from(3.14);
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #154024 <https://github.com/rust-lang/rust/issues/154024>
|
||||
= note: `#[warn(float_literal_f32_fallback)]` on by default
|
||||
= note: `#[warn(float_literal_f32_fallback)]` (part of `#[warn(future_incompatible)]`) on by default
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
||||
|
||||
Reference in New Issue
Block a user