1use std::cell::OnceCell;
2use std::ops::ControlFlow;
3
4use rustc_data_structures::fx::FxHashSet;
5use rustc_data_structures::graph;
6use rustc_data_structures::graph::vec_graph::VecGraph;
7use rustc_data_structures::unord::{UnordMap, UnordSet};
8use rustc_hir::attrs::DivergingFallbackBehavior;
9use rustc_hir::def::{DefKind, Res};
10use rustc_hir::def_id::DefId;
11use rustc_hir::intravisit::{InferKind, Visitor};
12use rustc_hir::{self as hir, CRATE_HIR_ID, HirId};
13use rustc_lint::builtin::FLOAT_LITERAL_F32_FALLBACK;
14use rustc_middle::ty::{self, FloatVid, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable};
15use rustc_session::lint;
16use rustc_span::def_id::LocalDefId;
17use rustc_span::{DUMMY_SP, Span};
18use rustc_trait_selection::traits::{ObligationCause, ObligationCtxt};
19use tracing::debug;
20
21use crate::{FnCtxt, diagnostics};
22
23impl<'tcx> FnCtxt<'_, 'tcx> {
24 pub(super) fn type_inference_fallback(&self) {
27 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_typeck/src/fallback.rs:27",
"rustc_hir_typeck::fallback", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_typeck/src/fallback.rs"),
::tracing_core::__macro_support::Option::Some(27u32),
::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::fallback"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("type-inference-fallback start obligations: {0:#?}",
self.fulfillment_cx.borrow_mut().pending_obligations()) as
&dyn Value))])
});
} else { ; }
};debug!(
28 "type-inference-fallback start obligations: {:#?}",
29 self.fulfillment_cx.borrow_mut().pending_obligations()
30 );
31
32 self.select_obligations_where_possible(|_| {});
34
35 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_typeck/src/fallback.rs:35",
"rustc_hir_typeck::fallback", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_typeck/src/fallback.rs"),
::tracing_core::__macro_support::Option::Some(35u32),
::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::fallback"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("type-inference-fallback post selection obligations: {0:#?}",
self.fulfillment_cx.borrow_mut().pending_obligations()) as
&dyn Value))])
});
} else { ; }
};debug!(
36 "type-inference-fallback post selection obligations: {:#?}",
37 self.fulfillment_cx.borrow_mut().pending_obligations()
38 );
39
40 let fallback_occurred = self.fallback_types();
41
42 if fallback_occurred {
43 self.select_obligations_where_possible(|_| {});
45 }
46 }
47
48 fn fallback_types(&self) -> bool {
49 let unresolved_variables = self.unresolved_variables();
51
52 if unresolved_variables.is_empty() {
53 return false;
54 }
55
56 let (diverging_fallback, diverging_fallback_ty) =
57 self.calculate_diverging_fallback(&unresolved_variables);
58 let fallback_to_f32 = self.calculate_fallback_to_f32(&unresolved_variables);
59
60 let mut fallback_occurred = false;
64 for ty in unresolved_variables {
65 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_typeck/src/fallback.rs:65",
"rustc_hir_typeck::fallback", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_typeck/src/fallback.rs"),
::tracing_core::__macro_support::Option::Some(65u32),
::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::fallback"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("unsolved_variable = {0:?}",
ty) as &dyn Value))])
});
} else { ; }
};debug!("unsolved_variable = {:?}", ty);
66 fallback_occurred |= self.fallback_if_possible(
67 ty,
68 &diverging_fallback,
69 diverging_fallback_ty,
70 &fallback_to_f32,
71 );
72 }
73
74 fallback_occurred
75 }
76
77 fn fallback_if_possible(
94 &self,
95 ty: Ty<'tcx>,
96 diverging_fallback: &UnordSet<Ty<'tcx>>,
97 diverging_fallback_ty: Ty<'tcx>,
98 fallback_to_f32: &UnordSet<FloatVid>,
99 ) -> bool {
100 let fallback = match ty.kind() {
119 _ if let Some(e) = self.tainted_by_errors() => Ty::new_error(self.tcx, e),
120 ty::Infer(ty::IntVar(_)) => self.tcx.types.i32,
121 ty::Infer(ty::FloatVar(vid)) if fallback_to_f32.contains(vid) => self.tcx.types.f32,
122 ty::Infer(ty::FloatVar(_)) => self.tcx.types.f64,
123 _ if diverging_fallback.contains(&ty) => {
124 self.diverging_fallback_has_occurred.set(true);
125 diverging_fallback_ty
126 }
127 _ => return false,
128 };
129 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_typeck/src/fallback.rs:129",
"rustc_hir_typeck::fallback", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_typeck/src/fallback.rs"),
::tracing_core::__macro_support::Option::Some(129u32),
::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::fallback"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("fallback_if_possible(ty={0:?}): defaulting to `{1:?}`",
ty, fallback) as &dyn Value))])
});
} else { ; }
};debug!("fallback_if_possible(ty={:?}): defaulting to `{:?}`", ty, fallback);
130
131 let span = ty.ty_vid().map_or(DUMMY_SP, |vid| self.infcx.type_var_origin(vid).span);
132 self.demand_eqtype(span, ty, fallback);
133 true
134 }
135
136 fn calculate_fallback_to_f32(&self, unresolved_variables: &[Ty<'tcx>]) -> UnordSet<FloatVid> {
150 if unresolved_variables.iter().all(|ty| ty.float_vid().is_none()) {
156 return UnordSet::new();
157 }
158 let roots: UnordSet<ty::FloatVid> = self.from_float_for_f32_root_vids();
159 if roots.is_empty() {
160 return UnordSet::new();
163 }
164 let fallback_to_f32 = unresolved_variables
168 .iter()
169 .flat_map(|ty| ty.float_vid())
170 .filter(|vid| roots.contains(&self.root_float_var(*vid)))
171 .inspect(|vid| {
172 let origin = self.float_var_origin(*vid);
173 let mut literal = self.tcx.sess.source_map().span_to_snippet(origin.span).ok();
175 if let Some(ref mut literal) = literal
177 && literal.ends_with('.')
178 {
179 literal.pop();
180 }
181 self.tcx.emit_node_span_lint(
182 FLOAT_LITERAL_F32_FALLBACK,
183 origin.lint_id.unwrap_or(CRATE_HIR_ID),
184 origin.span,
185 diagnostics::FloatLiteralF32Fallback {
186 span: literal.as_ref().map(|_| origin.span),
187 literal: literal.unwrap_or_default(),
188 },
189 );
190 })
191 .collect();
192 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_typeck/src/fallback.rs:192",
"rustc_hir_typeck::fallback", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_typeck/src/fallback.rs"),
::tracing_core::__macro_support::Option::Some(192u32),
::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::fallback"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("calculate_fallback_to_f32: fallback_to_f32={0:?}",
fallback_to_f32) as &dyn Value))])
});
} else { ; }
};debug!("calculate_fallback_to_f32: fallback_to_f32={:?}", fallback_to_f32);
193 fallback_to_f32
194 }
195
196 fn calculate_diverging_fallback(
197 &self,
198 unresolved_variables: &[Ty<'tcx>],
199 ) -> (UnordSet<Ty<'tcx>>, Ty<'tcx>) {
200 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_typeck/src/fallback.rs:200",
"rustc_hir_typeck::fallback", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_typeck/src/fallback.rs"),
::tracing_core::__macro_support::Option::Some(200u32),
::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::fallback"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("calculate_diverging_fallback({0:?})",
unresolved_variables) as &dyn Value))])
});
} else { ; }
};debug!("calculate_diverging_fallback({:?})", unresolved_variables);
201
202 let diverging_fallback_ty = match self.diverging_fallback_behavior {
203 DivergingFallbackBehavior::ToUnit => self.tcx.types.unit,
204 DivergingFallbackBehavior::ToNever => self.tcx.types.never,
205 DivergingFallbackBehavior::NoFallback => {
206 return (UnordSet::new(), self.tcx.types.unit);
208 }
209 };
210
211 let coercion_graph = self.create_coercion_graph();
214
215 let unsolved_vids = unresolved_variables.iter().filter_map(|ty| ty.ty_vid());
218
219 let diverging_roots: UnordSet<ty::TyVid> = self
226 .diverging_type_vars
227 .borrow()
228 .iter()
229 .map(|&ty_id| self.shallow_resolve(Ty::new_var(self.tcx, ty_id)))
230 .filter_map(|ty| ty.ty_vid())
231 .map(|vid| self.root_var(vid))
232 .collect();
233 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_typeck/src/fallback.rs:233",
"rustc_hir_typeck::fallback", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_typeck/src/fallback.rs"),
::tracing_core::__macro_support::Option::Some(233u32),
::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::fallback"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("calculate_diverging_fallback: diverging_type_vars={0:?}",
self.diverging_type_vars.borrow()) as &dyn Value))])
});
} else { ; }
};debug!(
234 "calculate_diverging_fallback: diverging_type_vars={:?}",
235 self.diverging_type_vars.borrow()
236 );
237 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_typeck/src/fallback.rs:237",
"rustc_hir_typeck::fallback", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_typeck/src/fallback.rs"),
::tracing_core::__macro_support::Option::Some(237u32),
::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::fallback"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("calculate_diverging_fallback: diverging_roots={0:?}",
diverging_roots) as &dyn Value))])
});
} else { ; }
};debug!("calculate_diverging_fallback: diverging_roots={:?}", diverging_roots);
238
239 let mut diverging_vids = ::alloc::vec::Vec::new()vec![];
244 for unsolved_vid in unsolved_vids {
245 let root_vid = self.root_var(unsolved_vid);
246 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_typeck/src/fallback.rs:246",
"rustc_hir_typeck::fallback", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_typeck/src/fallback.rs"),
::tracing_core::__macro_support::Option::Some(246u32),
::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::fallback"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("calculate_diverging_fallback: unsolved_vid={0:?} root_vid={1:?} diverges={2:?}",
unsolved_vid, root_vid, diverging_roots.contains(&root_vid))
as &dyn Value))])
});
} else { ; }
};debug!(
247 "calculate_diverging_fallback: unsolved_vid={:?} root_vid={:?} diverges={:?}",
248 unsolved_vid,
249 root_vid,
250 diverging_roots.contains(&root_vid),
251 );
252 if diverging_roots.contains(&root_vid) {
253 diverging_vids.push(unsolved_vid);
254
255 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_typeck/src/fallback.rs:255",
"rustc_hir_typeck::fallback", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_typeck/src/fallback.rs"),
::tracing_core::__macro_support::Option::Some(255u32),
::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::fallback"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("calculate_diverging_fallback: root_vid={0:?} reaches {1:?}",
root_vid,
graph::depth_first_search(&coercion_graph,
root_vid).collect::<Vec<_>>()) as &dyn Value))])
});
} else { ; }
};debug!(
256 "calculate_diverging_fallback: root_vid={:?} reaches {:?}",
257 root_vid,
258 graph::depth_first_search(&coercion_graph, root_vid).collect::<Vec<_>>()
259 );
260 }
261 }
262
263 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_typeck/src/fallback.rs:263",
"rustc_hir_typeck::fallback", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_typeck/src/fallback.rs"),
::tracing_core::__macro_support::Option::Some(263u32),
::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::fallback"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("obligations: {0:#?}",
self.fulfillment_cx.borrow_mut().pending_obligations()) as
&dyn Value))])
});
} else { ; }
};debug!("obligations: {:#?}", self.fulfillment_cx.borrow_mut().pending_obligations());
264
265 let mut diverging_fallback = UnordSet::with_capacity(diverging_vids.len());
266 let unsafe_infer_vars = OnceCell::new();
267
268 self.lint_obligations_broken_by_never_type_fallback_change(
269 &diverging_vids,
270 &coercion_graph,
271 );
272
273 for &diverging_vid in &diverging_vids {
274 let diverging_ty = Ty::new_var(self.tcx, diverging_vid);
275 let root_vid = self.root_var(diverging_vid);
276
277 self.lint_never_type_fallback_flowing_into_unsafe_code(
278 &unsafe_infer_vars,
279 &coercion_graph,
280 root_vid,
281 );
282
283 diverging_fallback.insert(diverging_ty);
284 }
285
286 (diverging_fallback, diverging_fallback_ty)
287 }
288
289 fn lint_never_type_fallback_flowing_into_unsafe_code(
290 &self,
291 unsafe_infer_vars: &OnceCell<UnordMap<ty::TyVid, (HirId, Span, UnsafeUseReason)>>,
292 coercion_graph: &VecGraph<ty::TyVid, true>,
293 root_vid: ty::TyVid,
294 ) {
295 let unsafe_infer_vars = unsafe_infer_vars.get_or_init(|| {
296 let unsafe_infer_vars = compute_unsafe_infer_vars(self, self.body_def_id);
297 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_typeck/src/fallback.rs:297",
"rustc_hir_typeck::fallback", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_typeck/src/fallback.rs"),
::tracing_core::__macro_support::Option::Some(297u32),
::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::fallback"),
::tracing_core::field::FieldSet::new(&["unsafe_infer_vars"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&unsafe_infer_vars)
as &dyn Value))])
});
} else { ; }
};debug!(?unsafe_infer_vars);
298 unsafe_infer_vars
299 });
300
301 let affected_unsafe_infer_vars =
302 graph::depth_first_search_as_undirected(&coercion_graph, root_vid)
303 .filter_map(|x| unsafe_infer_vars.get(&x).copied())
304 .collect::<Vec<_>>();
305
306 let sugg = self.try_to_suggest_annotations(&[root_vid], coercion_graph);
307
308 for (hir_id, span, reason) in affected_unsafe_infer_vars {
309 self.tcx.emit_node_span_lint(
310 lint::builtin::NEVER_TYPE_FALLBACK_FLOWING_INTO_UNSAFE,
311 hir_id,
312 span,
313 match reason {
314 UnsafeUseReason::Call => {
315 diagnostics::NeverTypeFallbackFlowingIntoUnsafe::Call { sugg: sugg.clone() }
316 }
317 UnsafeUseReason::Method => {
318 diagnostics::NeverTypeFallbackFlowingIntoUnsafe::Method {
319 sugg: sugg.clone(),
320 }
321 }
322 UnsafeUseReason::Path => {
323 diagnostics::NeverTypeFallbackFlowingIntoUnsafe::Path { sugg: sugg.clone() }
324 }
325 UnsafeUseReason::UnionField => {
326 diagnostics::NeverTypeFallbackFlowingIntoUnsafe::UnionField {
327 sugg: sugg.clone(),
328 }
329 }
330 UnsafeUseReason::Deref => {
331 diagnostics::NeverTypeFallbackFlowingIntoUnsafe::Deref {
332 sugg: sugg.clone(),
333 }
334 }
335 },
336 );
337 }
338 }
339
340 fn lint_obligations_broken_by_never_type_fallback_change(
341 &self,
342 diverging_vids: &[ty::TyVid],
343 coercions: &VecGraph<ty::TyVid, true>,
344 ) {
345 let DivergingFallbackBehavior::ToUnit = self.diverging_fallback_behavior else { return };
346
347 if diverging_vids.is_empty() {
349 return;
350 }
351
352 let remaining_errors_if_fallback_to = |fallback| {
354 self.probe(|_| {
355 let obligations = self.fulfillment_cx.borrow().pending_obligations();
356 let ocx = ObligationCtxt::new_with_diagnostics(&self.infcx);
357 ocx.register_obligations(obligations.iter().cloned());
358
359 for &diverging_vid in diverging_vids {
360 let diverging_ty = Ty::new_var(self.tcx, diverging_vid);
361
362 ocx.eq(&ObligationCause::dummy(), self.param_env, diverging_ty, fallback)
363 .expect("expected diverging var to be unconstrained");
364 }
365
366 ocx.try_evaluate_obligations()
367 })
368 };
369
370 let unit_errors = remaining_errors_if_fallback_to(self.tcx.types.unit);
373 if unit_errors.is_empty()
374 && let mut never_errors = remaining_errors_if_fallback_to(self.tcx.types.never)
375 && let [never_error, ..] = never_errors.as_mut_slice()
376 {
377 self.adjust_fulfillment_error_for_expr_obligation(never_error);
378 let sugg = self.try_to_suggest_annotations(diverging_vids, coercions);
379 self.tcx.emit_node_span_lint(
380 lint::builtin::DEPENDENCY_ON_UNIT_NEVER_TYPE_FALLBACK,
381 self.tcx.local_def_id_to_hir_id(self.body_def_id),
382 self.tcx.def_span(self.body_def_id),
383 diagnostics::DependencyOnUnitNeverTypeFallback {
384 obligation_span: never_error.obligation.cause.span,
385 obligation: never_error.obligation.predicate,
386 sugg,
387 },
388 )
389 }
390 }
391
392 fn create_coercion_graph(&self) -> VecGraph<ty::TyVid, true> {
395 let pending_obligations = self.fulfillment_cx.borrow_mut().pending_obligations();
396 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_typeck/src/fallback.rs:396",
"rustc_hir_typeck::fallback", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_typeck/src/fallback.rs"),
::tracing_core::__macro_support::Option::Some(396u32),
::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::fallback"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("create_coercion_graph: pending_obligations={0:?}",
pending_obligations) as &dyn Value))])
});
} else { ; }
};debug!("create_coercion_graph: pending_obligations={:?}", pending_obligations);
397 let coercion_edges: Vec<(ty::TyVid, ty::TyVid)> = pending_obligations
398 .into_iter()
399 .filter_map(|obligation| {
400 obligation.predicate.kind().no_bound_vars()
403 })
404 .filter_map(|atom| {
405 let (a, b) = match atom {
414 ty::PredicateKind::Coerce(ty::CoercePredicate { a, b }) => (a, b),
415 ty::PredicateKind::Subtype(ty::SubtypePredicate { a_is_expected: _, a, b }) => {
416 (a, b)
417 }
418 _ => return None,
419 };
420
421 let a_vid = self.root_vid(a)?;
422 let b_vid = self.root_vid(b)?;
423 Some((a_vid, b_vid))
424 })
425 .collect();
426 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_typeck/src/fallback.rs:426",
"rustc_hir_typeck::fallback", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_typeck/src/fallback.rs"),
::tracing_core::__macro_support::Option::Some(426u32),
::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::fallback"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("create_coercion_graph: coercion_edges={0:?}",
coercion_edges) as &dyn Value))])
});
} else { ; }
};debug!("create_coercion_graph: coercion_edges={:?}", coercion_edges);
427 let num_ty_vars = self.num_ty_vars();
428
429 VecGraph::new(num_ty_vars, coercion_edges)
430 }
431
432 fn root_vid(&self, ty: Ty<'tcx>) -> Option<ty::TyVid> {
434 Some(self.root_var(self.shallow_resolve(ty).ty_vid()?))
435 }
436
437 pub(crate) fn root_float_vid(&self, ty: Ty<'tcx>) -> Option<ty::FloatVid> {
439 Some(self.root_float_var(self.shallow_resolve(ty).float_vid()?))
440 }
441
442 fn try_to_suggest_annotations(
445 &self,
446 diverging_vids: &[ty::TyVid],
447 coercions: &VecGraph<ty::TyVid, true>,
448 ) -> diagnostics::SuggestAnnotations {
449 let body = self.tcx.hir_body_owned_by(self.body_def_id);
450 let suggestions = diverging_vids
454 .iter()
455 .copied()
456 .filter_map(|vid| {
457 let reachable_vids =
458 graph::depth_first_search_as_undirected(coercions, vid).collect();
459 AnnotateUnitFallbackVisitor { reachable_vids, fcx: self }
460 .visit_expr(body.value)
461 .break_value()
462 })
463 .collect();
464 diagnostics::SuggestAnnotations { suggestions }
465 }
466}
467
468struct AnnotateUnitFallbackVisitor<'a, 'tcx> {
471 reachable_vids: FxHashSet<ty::TyVid>,
472 fcx: &'a FnCtxt<'a, 'tcx>,
473}
474impl<'tcx> AnnotateUnitFallbackVisitor<'_, 'tcx> {
475 fn suggest_for_segment(
481 &self,
482 arg_segment: &'tcx hir::PathSegment<'tcx>,
483 def_id: DefId,
484 id: HirId,
485 ) -> ControlFlow<diagnostics::SuggestAnnotation> {
486 if arg_segment.args.is_none()
487 && let Some(all_args) = self.fcx.typeck_results.borrow().node_args_opt(id)
488 && let generics = self.fcx.tcx.generics_of(def_id)
489 && let args = all_args[generics.parent_count..].iter().zip(&generics.own_params)
490 && args.clone().all(|(_, param)| #[allow(non_exhaustive_omitted_patterns)] match param.kind {
ty::GenericParamDefKind::Type { .. } | ty::GenericParamDefKind::Lifetime
=> true,
_ => false,
}matches!(param.kind, ty::GenericParamDefKind::Type { .. } | ty::GenericParamDefKind::Lifetime))
492 {
493 let non_apit_type_args = args.filter(|(_, param)| {
495 #[allow(non_exhaustive_omitted_patterns)] match param.kind {
ty::GenericParamDefKind::Type { synthetic: false, .. } => true,
_ => false,
}matches!(param.kind, ty::GenericParamDefKind::Type { synthetic: false, .. })
496 });
497 let n_tys = non_apit_type_args.clone().count();
498 for (idx, (arg, _)) in non_apit_type_args.enumerate() {
499 if let Some(ty) = arg.as_type()
500 && let Some(vid) = self.fcx.root_vid(ty)
501 && self.reachable_vids.contains(&vid)
502 {
503 return ControlFlow::Break(diagnostics::SuggestAnnotation::Turbo(
504 arg_segment.ident.span.shrink_to_hi(),
505 n_tys,
506 idx,
507 ));
508 }
509 }
510 }
511 ControlFlow::Continue(())
512 }
513}
514impl<'tcx> Visitor<'tcx> for AnnotateUnitFallbackVisitor<'_, 'tcx> {
515 type Result = ControlFlow<diagnostics::SuggestAnnotation>;
516
517 fn visit_infer(
518 &mut self,
519 inf_id: HirId,
520 inf_span: Span,
521 _kind: InferKind<'tcx>,
522 ) -> Self::Result {
523 if let Some(ty) = self.fcx.typeck_results.borrow().node_type_opt(inf_id)
525 && let Some(vid) = self.fcx.root_vid(ty)
526 && self.reachable_vids.contains(&vid)
527 && inf_span.can_be_used_for_suggestions()
528 {
529 return ControlFlow::Break(diagnostics::SuggestAnnotation::Unit(inf_span));
530 }
531
532 ControlFlow::Continue(())
533 }
534
535 fn visit_qpath(
536 &mut self,
537 qpath: &'tcx rustc_hir::QPath<'tcx>,
538 id: HirId,
539 span: Span,
540 ) -> Self::Result {
541 let arg_segment = match qpath {
542 hir::QPath::Resolved(_, path) => {
543 path.segments.last().expect("paths should have a segment")
544 }
545 hir::QPath::TypeRelative(_, segment) => segment,
546 };
547 if let Some(def_id) = self.fcx.typeck_results.borrow().qpath_res(qpath, id).opt_def_id()
549 && span.can_be_used_for_suggestions()
550 {
551 self.suggest_for_segment(arg_segment, def_id, id)?;
552 }
553 hir::intravisit::walk_qpath(self, qpath, id)
554 }
555
556 fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Self::Result {
557 if let hir::ExprKind::Closure(&hir::Closure { body, .. })
558 | hir::ExprKind::ConstBlock(hir::ConstBlock { body, .. }) = expr.kind
559 {
560 self.visit_body(self.fcx.tcx.hir_body(body))?;
561 }
562
563 if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind
566 && let Res::Def(DefKind::AssocFn, def_id) = path.res
567 && self.fcx.tcx.trait_of_assoc(def_id).is_some()
568 && let Some(args) = self.fcx.typeck_results.borrow().node_args_opt(expr.hir_id)
569 && let self_ty = args.type_at(0)
570 && let Some(vid) = self.fcx.root_vid(self_ty)
571 && self.reachable_vids.contains(&vid)
572 && let [.., trait_segment, _method_segment] = path.segments
573 && expr.span.can_be_used_for_suggestions()
574 {
575 let span = path.span.shrink_to_lo().to(trait_segment.ident.span);
576 return ControlFlow::Break(diagnostics::SuggestAnnotation::Path(span));
577 }
578
579 if let hir::ExprKind::MethodCall(segment, ..) = expr.kind
581 && let Some(def_id) =
582 self.fcx.typeck_results.borrow().type_dependent_def_id(expr.hir_id)
583 && expr.span.can_be_used_for_suggestions()
584 {
585 self.suggest_for_segment(segment, def_id, expr.hir_id)?;
586 }
587
588 hir::intravisit::walk_expr(self, expr)
589 }
590
591 fn visit_local(&mut self, local: &'tcx hir::LetStmt<'tcx>) -> Self::Result {
592 if let hir::LocalSource::Normal = local.source
594 && let None = local.ty
595 && let Some(ty) = self.fcx.typeck_results.borrow().node_type_opt(local.hir_id)
596 && let Some(vid) = self.fcx.root_vid(ty)
597 && self.reachable_vids.contains(&vid)
598 && local.span.can_be_used_for_suggestions()
599 {
600 return ControlFlow::Break(diagnostics::SuggestAnnotation::Local(
601 local.pat.span.shrink_to_hi(),
602 ));
603 }
604 hir::intravisit::walk_local(self, local)
605 }
606}
607
608#[derive(#[automatically_derived]
impl ::core::fmt::Debug for UnsafeUseReason {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f,
match self {
UnsafeUseReason::Call => "Call",
UnsafeUseReason::Method => "Method",
UnsafeUseReason::Path => "Path",
UnsafeUseReason::UnionField => "UnionField",
UnsafeUseReason::Deref => "Deref",
})
}
}Debug, #[automatically_derived]
impl ::core::marker::Copy for UnsafeUseReason { }Copy, #[automatically_derived]
impl ::core::clone::Clone for UnsafeUseReason {
#[inline]
fn clone(&self) -> UnsafeUseReason { *self }
}Clone)]
609pub(crate) enum UnsafeUseReason {
610 Call,
611 Method,
612 Path,
613 UnionField,
614 Deref,
615}
616
617fn compute_unsafe_infer_vars<'a, 'tcx>(
634 fcx: &'a FnCtxt<'a, 'tcx>,
635 body_def_id: LocalDefId,
636) -> UnordMap<ty::TyVid, (HirId, Span, UnsafeUseReason)> {
637 let body = fcx.tcx.hir_body_owned_by(body_def_id);
638 let mut res = UnordMap::default();
639
640 struct UnsafeInferVarsVisitor<'a, 'tcx> {
641 fcx: &'a FnCtxt<'a, 'tcx>,
642 res: &'a mut UnordMap<ty::TyVid, (HirId, Span, UnsafeUseReason)>,
643 }
644
645 impl Visitor<'_> for UnsafeInferVarsVisitor<'_, '_> {
646 fn visit_expr(&mut self, ex: &'_ hir::Expr<'_>) {
647 let typeck_results = self.fcx.typeck_results.borrow();
648
649 match ex.kind {
650 hir::ExprKind::MethodCall(..) => {
651 if let Some(def_id) = typeck_results.type_dependent_def_id(ex.hir_id)
652 && let method_ty =
653 self.fcx.tcx.type_of(def_id).instantiate_identity().skip_norm_wip()
654 && let sig = method_ty.fn_sig(self.fcx.tcx)
655 && sig.safety().is_unsafe()
656 {
657 let mut collector = InferVarCollector {
658 value: (ex.hir_id, ex.span, UnsafeUseReason::Method),
659 res: self.res,
660 };
661
662 typeck_results
664 .node_args(ex.hir_id)
665 .types()
666 .for_each(|t| t.visit_with(&mut collector));
667 }
668 }
669
670 hir::ExprKind::Call(func, ..) => {
671 let func_ty = typeck_results.expr_ty(func);
672
673 if func_ty.is_fn()
674 && let sig = func_ty.fn_sig(self.fcx.tcx)
675 && sig.safety().is_unsafe()
676 {
677 let mut collector = InferVarCollector {
678 value: (ex.hir_id, ex.span, UnsafeUseReason::Call),
679 res: self.res,
680 };
681
682 typeck_results
687 .node_args(func.hir_id)
688 .types()
689 .for_each(|t| t.visit_with(&mut collector));
690
691 sig.output().visit_with(&mut collector);
693 }
694 }
695
696 hir::ExprKind::Path(_) => {
700 let ty = typeck_results.expr_ty(ex);
701
702 if ty.is_fn()
705 && let sig = ty.fn_sig(self.fcx.tcx)
706 && sig.safety().is_unsafe()
707 {
708 let mut collector = InferVarCollector {
709 value: (ex.hir_id, ex.span, UnsafeUseReason::Path),
710 res: self.res,
711 };
712
713 typeck_results
715 .node_args(ex.hir_id)
716 .types()
717 .for_each(|t| t.visit_with(&mut collector));
718 }
719 }
720
721 hir::ExprKind::Unary(hir::UnOp::Deref, pointer) => {
722 if let ty::RawPtr(pointee, _) = typeck_results.expr_ty(pointer).kind() {
723 pointee.visit_with(&mut InferVarCollector {
724 value: (ex.hir_id, ex.span, UnsafeUseReason::Deref),
725 res: self.res,
726 });
727 }
728 }
729
730 hir::ExprKind::Field(base, _) => {
731 let base_ty = typeck_results.expr_ty(base);
732
733 if base_ty.is_union() {
734 typeck_results.expr_ty(ex).visit_with(&mut InferVarCollector {
735 value: (ex.hir_id, ex.span, UnsafeUseReason::UnionField),
736 res: self.res,
737 });
738 }
739 }
740
741 _ => (),
742 };
743
744 hir::intravisit::walk_expr(self, ex);
745 }
746 }
747
748 struct InferVarCollector<'r, V> {
749 value: V,
750 res: &'r mut UnordMap<ty::TyVid, V>,
751 }
752
753 impl<'tcx, V: Copy> ty::TypeVisitor<TyCtxt<'tcx>> for InferVarCollector<'_, V> {
754 fn visit_ty(&mut self, t: Ty<'tcx>) {
755 if let Some(vid) = t.ty_vid() {
756 _ = self.res.try_insert(vid, self.value);
757 } else {
758 t.super_visit_with(self)
759 }
760 }
761 }
762
763 UnsafeInferVarsVisitor { fcx, res: &mut res }.visit_expr(&body.value);
764
765 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_typeck/src/fallback.rs:765",
"rustc_hir_typeck::fallback", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_typeck/src/fallback.rs"),
::tracing_core::__macro_support::Option::Some(765u32),
::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::fallback"),
::tracing_core::field::FieldSet::new(&["message", "res"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("collected the following unsafe vars for {0:?}",
body_def_id) as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&res) as
&dyn Value))])
});
} else { ; }
};debug!(?res, "collected the following unsafe vars for {body_def_id:?}");
766
767 res
768}