Skip to content

Commit c8334ce

Browse files
Move autoderef to rustc_hir_analysis
1 parent ef4046e commit c8334ce

File tree

16 files changed

+70
-46
lines changed

16 files changed

+70
-46
lines changed

compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl

+4
Original file line numberDiff line numberDiff line change
@@ -120,3 +120,7 @@ hir_analysis_self_in_impl_self =
120120
121121
hir_analysis_linkage_type =
122122
invalid type for variable with `#[linkage]` attribute
123+
124+
hir_analysis_auto_deref_reached_recursion_limit = reached the recursion limit while auto-dereferencing `{$ty}`
125+
.label = deref recursion limit reached
126+
.help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]` attribute to your crate (`{$crate_name}`)

compiler/rustc_error_messages/locales/en-US/trait_selection.ftl

-4
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,6 @@ trait_selection_dump_vtable_entries = vtable entries for `{$trait_ref}`: {$entri
22
33
trait_selection_unable_to_construct_constant_value = unable to construct a constant value for the unevaluated constant {$unevaluated}
44
5-
trait_selection_auto_deref_reached_recursion_limit = reached the recursion limit while auto-dereferencing `{$ty}`
6-
.label = deref recursion limit reached
7-
.help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]` attribute to your crate (`{$crate_name}`)
8-
95
trait_selection_empty_on_clause_in_rustc_on_unimplemented = empty `on`-clause in `#[rustc_on_unimplemented]`
106
.label = empty on-clause here
117

compiler/rustc_trait_selection/src/autoderef.rs renamed to compiler/rustc_hir_analysis/src/autoderef.rs

+4
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,10 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
178178
self.state.obligations
179179
}
180180

181+
pub fn current_obligations(&self) -> Vec<traits::PredicateObligation<'tcx>> {
182+
self.state.obligations.clone()
183+
}
184+
181185
pub fn steps(&self) -> &[(Ty<'tcx>, AutoderefKind)] {
182186
&self.state.steps
183187
}

compiler/rustc_hir_analysis/src/check/wfcheck.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
use crate::autoderef::Autoderef;
12
use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter};
3+
24
use hir::def::DefKind;
35
use rustc_ast as ast;
46
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
@@ -22,7 +24,6 @@ use rustc_session::parse::feature_err;
2224
use rustc_span::symbol::{sym, Ident, Symbol};
2325
use rustc_span::{Span, DUMMY_SP};
2426
use rustc_target::spec::abi::Abi;
25-
use rustc_trait_selection::autoderef::Autoderef;
2627
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
2728
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
2829
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;

compiler/rustc_hir_analysis/src/errors.rs

+12
Original file line numberDiff line numberDiff line change
@@ -300,3 +300,15 @@ pub(crate) struct LinkageType {
300300
#[primary_span]
301301
pub span: Span,
302302
}
303+
304+
#[derive(Diagnostic)]
305+
#[help]
306+
#[diag(hir_analysis_auto_deref_reached_recursion_limit, code = "E0055")]
307+
pub struct AutoDerefReachedRecursionLimit<'a> {
308+
#[primary_span]
309+
#[label]
310+
pub span: Span,
311+
pub ty: Ty<'a>,
312+
pub suggested_limit: rustc_session::Limit,
313+
pub crate_name: Symbol,
314+
}

compiler/rustc_hir_analysis/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ extern crate rustc_middle;
8484
pub mod check;
8585

8686
pub mod astconv;
87+
pub mod autoderef;
8788
mod bounds;
8889
mod check_unused;
8990
mod coherence;

compiler/rustc_hir_typeck/src/autoderef.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22
use super::method::MethodCallee;
33
use super::{FnCtxt, PlaceOp};
44

5+
use rustc_hir_analysis::autoderef::{Autoderef, AutoderefKind};
56
use rustc_infer::infer::InferOk;
67
use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref};
78
use rustc_middle::ty::{self, Ty};
89
use rustc_span::Span;
9-
use rustc_trait_selection::autoderef::{Autoderef, AutoderefKind};
1010

1111
use std::iter;
1212

compiler/rustc_hir_typeck/src/callee.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use rustc_errors::{struct_span_err, Applicability, Diagnostic, ErrorGuaranteed,
88
use rustc_hir as hir;
99
use rustc_hir::def::{self, CtorKind, Namespace, Res};
1010
use rustc_hir::def_id::DefId;
11+
use rustc_hir_analysis::autoderef::Autoderef;
1112
use rustc_infer::{
1213
infer,
1314
traits::{self, Obligation},
@@ -25,7 +26,6 @@ use rustc_span::def_id::LocalDefId;
2526
use rustc_span::symbol::{sym, Ident};
2627
use rustc_span::Span;
2728
use rustc_target::spec::abi;
28-
use rustc_trait_selection::autoderef::Autoderef;
2929
use rustc_trait_selection::infer::InferCtxtExt as _;
3030
use rustc_trait_selection::traits::error_reporting::DefIdOrName;
3131
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;

compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use rustc_middle::ty::subst::GenericArgKind;
2020
use rustc_middle::ty::{self, Const, Ty, TyCtxt, TypeVisitable};
2121
use rustc_session::Session;
2222
use rustc_span::symbol::Ident;
23-
use rustc_span::{self, Span};
23+
use rustc_span::{self, Span, DUMMY_SP};
2424
use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode, ObligationCtxt};
2525

2626
use std::cell::{Cell, RefCell};
@@ -175,6 +175,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
175175
fn_sig
176176
})
177177
}),
178+
autoderef_steps: Box::new(|ty| {
179+
let mut autoderef = self.autoderef(DUMMY_SP, ty).silence_errors();
180+
let mut steps = vec![];
181+
while let Some((ty, _)) = autoderef.next() {
182+
steps.push((ty, autoderef.current_obligations()));
183+
}
184+
steps
185+
}),
178186
}
179187
}
180188

compiler/rustc_hir_typeck/src/method/probe.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use rustc_data_structures::fx::FxHashSet;
99
use rustc_errors::Applicability;
1010
use rustc_hir as hir;
1111
use rustc_hir::def::DefKind;
12+
use rustc_hir_analysis::autoderef::{self, Autoderef};
1213
use rustc_infer::infer::canonical::OriginalQueryValues;
1314
use rustc_infer::infer::canonical::{Canonical, QueryResponse};
1415
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
@@ -29,7 +30,6 @@ use rustc_span::lev_distance::{
2930
};
3031
use rustc_span::symbol::sym;
3132
use rustc_span::{symbol::Ident, Span, Symbol, DUMMY_SP};
32-
use rustc_trait_selection::autoderef::{self, Autoderef};
3333
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
3434
use rustc_trait_selection::traits::query::method_autoderef::MethodAutoderefBadTy;
3535
use rustc_trait_selection::traits::query::method_autoderef::{

compiler/rustc_hir_typeck/src/place_op.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@ use crate::{has_expected_num_generic_args, FnCtxt, PlaceOp};
33
use rustc_ast as ast;
44
use rustc_errors::Applicability;
55
use rustc_hir as hir;
6+
use rustc_hir_analysis::autoderef::Autoderef;
67
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
78
use rustc_infer::infer::InferOk;
89
use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref, PointerCast};
910
use rustc_middle::ty::adjustment::{AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
1011
use rustc_middle::ty::{self, Ty};
1112
use rustc_span::symbol::{sym, Ident};
1213
use rustc_span::Span;
13-
use rustc_trait_selection::autoderef::Autoderef;
1414
use std::slice;
1515

1616
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

compiler/rustc_infer/src/infer/error_reporting/mod.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ use crate::infer::ExpectedFound;
5555
use crate::traits::error_reporting::report_object_safety_error;
5656
use crate::traits::{
5757
IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode,
58+
PredicateObligation,
5859
};
5960

6061
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
@@ -91,8 +92,12 @@ pub mod nice_region_error;
9192
pub struct TypeErrCtxt<'a, 'tcx> {
9293
pub infcx: &'a InferCtxt<'tcx>,
9394
pub typeck_results: Option<std::cell::Ref<'a, ty::TypeckResults<'tcx>>>,
94-
pub normalize_fn_sig: Box<dyn Fn(ty::PolyFnSig<'tcx>) -> ty::PolyFnSig<'tcx> + 'a>,
9595
pub fallback_has_occurred: bool,
96+
97+
pub normalize_fn_sig: Box<dyn Fn(ty::PolyFnSig<'tcx>) -> ty::PolyFnSig<'tcx> + 'a>,
98+
99+
pub autoderef_steps:
100+
Box<dyn Fn(Ty<'tcx>) -> Vec<(Ty<'tcx>, Vec<PredicateObligation<'tcx>>)> + 'a>,
96101
}
97102

98103
impl TypeErrCtxt<'_, '_> {

compiler/rustc_infer/src/infer/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -688,6 +688,10 @@ impl<'tcx> InferCtxt<'tcx> {
688688
typeck_results: None,
689689
fallback_has_occurred: false,
690690
normalize_fn_sig: Box::new(|fn_sig| fn_sig),
691+
autoderef_steps: Box::new(|ty| {
692+
debug_assert!(false, "shouldn't be using autoderef_steps outside of typeck");
693+
vec![(ty, vec![])]
694+
}),
691695
}
692696
}
693697

compiler/rustc_trait_selection/src/errors.rs

-13
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use rustc_errors::{fluent, ErrorGuaranteed, Handler, IntoDiagnostic};
22
use rustc_macros::Diagnostic;
33
use rustc_middle::ty::{self, PolyTraitRef, Ty};
4-
use rustc_session::Limit;
54
use rustc_span::{Span, Symbol};
65

76
#[derive(Diagnostic)]
@@ -21,18 +20,6 @@ pub struct UnableToConstructConstantValue<'a> {
2120
pub unevaluated: ty::UnevaluatedConst<'a>,
2221
}
2322

24-
#[derive(Diagnostic)]
25-
#[help]
26-
#[diag(trait_selection_auto_deref_reached_recursion_limit, code = "E0055")]
27-
pub struct AutoDerefReachedRecursionLimit<'a> {
28-
#[primary_span]
29-
#[label]
30-
pub span: Span,
31-
pub ty: Ty<'a>,
32-
pub suggested_limit: Limit,
33-
pub crate_name: Symbol,
34-
}
35-
3623
#[derive(Diagnostic)]
3724
#[diag(trait_selection_empty_on_clause_in_rustc_on_unimplemented, code = "E0232")]
3825
pub struct EmptyOnClauseInOnUnimplemented {

compiler/rustc_trait_selection/src/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ extern crate rustc_middle;
3535
#[macro_use]
3636
extern crate smallvec;
3737

38-
pub mod autoderef;
3938
pub mod errors;
4039
pub mod infer;
4140
pub mod solve;

compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs

+24-21
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ use super::{
55
PredicateObligation,
66
};
77

8-
use crate::autoderef::Autoderef;
98
use crate::infer::InferCtxt;
109
use crate::traits::{NormalizeExt, ObligationCtxt};
1110

@@ -750,26 +749,30 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
750749
}
751750

752751
if let ty::Ref(region, base_ty, mutbl) = *real_ty.skip_binder().kind() {
753-
let mut autoderef = Autoderef::new(
754-
self,
755-
obligation.param_env,
756-
obligation.cause.body_id,
757-
span,
758-
base_ty,
759-
);
760-
if let Some(steps) = autoderef.find_map(|(ty, steps)| {
761-
// Re-add the `&`
762-
let ty = self.tcx.mk_ref(region, TypeAndMut { ty, mutbl });
763-
764-
// Remapping bound vars here
765-
let real_trait_pred_and_ty =
766-
real_trait_pred.map_bound(|inner_trait_pred| (inner_trait_pred, ty));
767-
let obligation = self.mk_trait_obligation_with_new_self_ty(
768-
obligation.param_env,
769-
real_trait_pred_and_ty,
770-
);
771-
Some(steps).filter(|_| self.predicate_may_hold(&obligation))
772-
}) {
752+
let autoderef = (self.autoderef_steps)(base_ty);
753+
if let Some(steps) =
754+
autoderef.into_iter().enumerate().find_map(|(steps, (ty, obligations))| {
755+
// Re-add the `&`
756+
let ty = self.tcx.mk_ref(region, TypeAndMut { ty, mutbl });
757+
758+
// Remapping bound vars here
759+
let real_trait_pred_and_ty =
760+
real_trait_pred.map_bound(|inner_trait_pred| (inner_trait_pred, ty));
761+
let obligation = self.mk_trait_obligation_with_new_self_ty(
762+
obligation.param_env,
763+
real_trait_pred_and_ty,
764+
);
765+
if obligations
766+
.iter()
767+
.chain([&obligation])
768+
.all(|obligation| self.predicate_may_hold(obligation))
769+
{
770+
Some(steps)
771+
} else {
772+
None
773+
}
774+
})
775+
{
773776
if steps > 0 {
774777
// Don't care about `&mut` because `DerefMut` is used less
775778
// often and user will not expect autoderef happens.

0 commit comments

Comments
 (0)