Move autoderef to rustc_hir_analysis

This commit is contained in:
Michael Goulet 2022-12-27 00:39:36 +00:00
parent ef4046e4f3
commit c8334ce60c
16 changed files with 69 additions and 45 deletions

View File

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

View File

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

View File

@ -178,6 +178,10 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
self.state.obligations self.state.obligations
} }
pub fn current_obligations(&self) -> Vec<traits::PredicateObligation<'tcx>> {
self.state.obligations.clone()
}
pub fn steps(&self) -> &[(Ty<'tcx>, AutoderefKind)] { pub fn steps(&self) -> &[(Ty<'tcx>, AutoderefKind)] {
&self.state.steps &self.state.steps
} }

View File

@ -1,4 +1,6 @@
use crate::autoderef::Autoderef;
use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter}; use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter};
use hir::def::DefKind; use hir::def::DefKind;
use rustc_ast as ast; use rustc_ast as ast;
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
@ -22,7 +24,6 @@ use rustc_session::parse::feature_err;
use rustc_span::symbol::{sym, Ident, Symbol}; use rustc_span::symbol::{sym, Ident, Symbol};
use rustc_span::{Span, DUMMY_SP}; use rustc_span::{Span, DUMMY_SP};
use rustc_target::spec::abi::Abi; use rustc_target::spec::abi::Abi;
use rustc_trait_selection::autoderef::Autoderef;
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _; use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;

View File

@ -300,3 +300,15 @@ pub(crate) struct LinkageType {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
} }
#[derive(Diagnostic)]
#[help]
#[diag(hir_analysis_auto_deref_reached_recursion_limit, code = "E0055")]
pub struct AutoDerefReachedRecursionLimit<'a> {
#[primary_span]
#[label]
pub span: Span,
pub ty: Ty<'a>,
pub suggested_limit: rustc_session::Limit,
pub crate_name: Symbol,
}

View File

@ -84,6 +84,7 @@ extern crate rustc_middle;
pub mod check; pub mod check;
pub mod astconv; pub mod astconv;
pub mod autoderef;
mod bounds; mod bounds;
mod check_unused; mod check_unused;
mod coherence; mod coherence;

View File

@ -2,11 +2,11 @@
use super::method::MethodCallee; use super::method::MethodCallee;
use super::{FnCtxt, PlaceOp}; use super::{FnCtxt, PlaceOp};
use rustc_hir_analysis::autoderef::{Autoderef, AutoderefKind};
use rustc_infer::infer::InferOk; use rustc_infer::infer::InferOk;
use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref}; use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref};
use rustc_middle::ty::{self, Ty}; use rustc_middle::ty::{self, Ty};
use rustc_span::Span; use rustc_span::Span;
use rustc_trait_selection::autoderef::{Autoderef, AutoderefKind};
use std::iter; use std::iter;

View File

@ -8,6 +8,7 @@ use rustc_errors::{struct_span_err, Applicability, Diagnostic, ErrorGuaranteed,
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::{self, CtorKind, Namespace, Res}; use rustc_hir::def::{self, CtorKind, Namespace, Res};
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_hir_analysis::autoderef::Autoderef;
use rustc_infer::{ use rustc_infer::{
infer, infer,
traits::{self, Obligation}, traits::{self, Obligation},
@ -25,7 +26,6 @@ use rustc_span::def_id::LocalDefId;
use rustc_span::symbol::{sym, Ident}; use rustc_span::symbol::{sym, Ident};
use rustc_span::Span; use rustc_span::Span;
use rustc_target::spec::abi; use rustc_target::spec::abi;
use rustc_trait_selection::autoderef::Autoderef;
use rustc_trait_selection::infer::InferCtxtExt as _; use rustc_trait_selection::infer::InferCtxtExt as _;
use rustc_trait_selection::traits::error_reporting::DefIdOrName; use rustc_trait_selection::traits::error_reporting::DefIdOrName;
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;

View File

@ -20,7 +20,7 @@ use rustc_middle::ty::subst::GenericArgKind;
use rustc_middle::ty::{self, Const, Ty, TyCtxt, TypeVisitable}; use rustc_middle::ty::{self, Const, Ty, TyCtxt, TypeVisitable};
use rustc_session::Session; use rustc_session::Session;
use rustc_span::symbol::Ident; use rustc_span::symbol::Ident;
use rustc_span::{self, Span}; use rustc_span::{self, Span, DUMMY_SP};
use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode, ObligationCtxt}; use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode, ObligationCtxt};
use std::cell::{Cell, RefCell}; use std::cell::{Cell, RefCell};
@ -175,6 +175,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
fn_sig fn_sig
}) })
}), }),
autoderef_steps: Box::new(|ty| {
let mut autoderef = self.autoderef(DUMMY_SP, ty).silence_errors();
let mut steps = vec![];
while let Some((ty, _)) = autoderef.next() {
steps.push((ty, autoderef.current_obligations()));
}
steps
}),
} }
} }

View File

@ -9,6 +9,7 @@ use rustc_data_structures::fx::FxHashSet;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::DefKind; use rustc_hir::def::DefKind;
use rustc_hir_analysis::autoderef::{self, Autoderef};
use rustc_infer::infer::canonical::OriginalQueryValues; use rustc_infer::infer::canonical::OriginalQueryValues;
use rustc_infer::infer::canonical::{Canonical, QueryResponse}; use rustc_infer::infer::canonical::{Canonical, QueryResponse};
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
@ -29,7 +30,6 @@ use rustc_span::lev_distance::{
}; };
use rustc_span::symbol::sym; use rustc_span::symbol::sym;
use rustc_span::{symbol::Ident, Span, Symbol, DUMMY_SP}; use rustc_span::{symbol::Ident, Span, Symbol, DUMMY_SP};
use rustc_trait_selection::autoderef::{self, Autoderef};
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
use rustc_trait_selection::traits::query::method_autoderef::MethodAutoderefBadTy; use rustc_trait_selection::traits::query::method_autoderef::MethodAutoderefBadTy;
use rustc_trait_selection::traits::query::method_autoderef::{ use rustc_trait_selection::traits::query::method_autoderef::{

View File

@ -3,6 +3,7 @@ use crate::{has_expected_num_generic_args, FnCtxt, PlaceOp};
use rustc_ast as ast; use rustc_ast as ast;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir_analysis::autoderef::Autoderef;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_infer::infer::InferOk; use rustc_infer::infer::InferOk;
use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref, PointerCast}; use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref, PointerCast};
@ -10,7 +11,6 @@ use rustc_middle::ty::adjustment::{AllowTwoPhase, AutoBorrow, AutoBorrowMutabili
use rustc_middle::ty::{self, Ty}; use rustc_middle::ty::{self, Ty};
use rustc_span::symbol::{sym, Ident}; use rustc_span::symbol::{sym, Ident};
use rustc_span::Span; use rustc_span::Span;
use rustc_trait_selection::autoderef::Autoderef;
use std::slice; use std::slice;
impl<'a, 'tcx> FnCtxt<'a, 'tcx> { impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

View File

@ -55,6 +55,7 @@ use crate::infer::ExpectedFound;
use crate::traits::error_reporting::report_object_safety_error; use crate::traits::error_reporting::report_object_safety_error;
use crate::traits::{ use crate::traits::{
IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode, IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode,
PredicateObligation,
}; };
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
@ -91,8 +92,12 @@ pub mod nice_region_error;
pub struct TypeErrCtxt<'a, 'tcx> { pub struct TypeErrCtxt<'a, 'tcx> {
pub infcx: &'a InferCtxt<'tcx>, pub infcx: &'a InferCtxt<'tcx>,
pub typeck_results: Option<std::cell::Ref<'a, ty::TypeckResults<'tcx>>>, pub typeck_results: Option<std::cell::Ref<'a, ty::TypeckResults<'tcx>>>,
pub normalize_fn_sig: Box<dyn Fn(ty::PolyFnSig<'tcx>) -> ty::PolyFnSig<'tcx> + 'a>,
pub fallback_has_occurred: bool, pub fallback_has_occurred: bool,
pub normalize_fn_sig: Box<dyn Fn(ty::PolyFnSig<'tcx>) -> ty::PolyFnSig<'tcx> + 'a>,
pub autoderef_steps:
Box<dyn Fn(Ty<'tcx>) -> Vec<(Ty<'tcx>, Vec<PredicateObligation<'tcx>>)> + 'a>,
} }
impl TypeErrCtxt<'_, '_> { impl TypeErrCtxt<'_, '_> {

View File

@ -688,6 +688,10 @@ impl<'tcx> InferCtxt<'tcx> {
typeck_results: None, typeck_results: None,
fallback_has_occurred: false, fallback_has_occurred: false,
normalize_fn_sig: Box::new(|fn_sig| fn_sig), normalize_fn_sig: Box::new(|fn_sig| fn_sig),
autoderef_steps: Box::new(|ty| {
debug_assert!(false, "shouldn't be using autoderef_steps outside of typeck");
vec![(ty, vec![])]
}),
} }
} }

View File

@ -1,7 +1,6 @@
use rustc_errors::{fluent, ErrorGuaranteed, Handler, IntoDiagnostic}; use rustc_errors::{fluent, ErrorGuaranteed, Handler, IntoDiagnostic};
use rustc_macros::Diagnostic; use rustc_macros::Diagnostic;
use rustc_middle::ty::{self, PolyTraitRef, Ty}; use rustc_middle::ty::{self, PolyTraitRef, Ty};
use rustc_session::Limit;
use rustc_span::{Span, Symbol}; use rustc_span::{Span, Symbol};
#[derive(Diagnostic)] #[derive(Diagnostic)]
@ -21,18 +20,6 @@ pub struct UnableToConstructConstantValue<'a> {
pub unevaluated: ty::UnevaluatedConst<'a>, pub unevaluated: ty::UnevaluatedConst<'a>,
} }
#[derive(Diagnostic)]
#[help]
#[diag(trait_selection_auto_deref_reached_recursion_limit, code = "E0055")]
pub struct AutoDerefReachedRecursionLimit<'a> {
#[primary_span]
#[label]
pub span: Span,
pub ty: Ty<'a>,
pub suggested_limit: Limit,
pub crate_name: Symbol,
}
#[derive(Diagnostic)] #[derive(Diagnostic)]
#[diag(trait_selection_empty_on_clause_in_rustc_on_unimplemented, code = "E0232")] #[diag(trait_selection_empty_on_clause_in_rustc_on_unimplemented, code = "E0232")]
pub struct EmptyOnClauseInOnUnimplemented { pub struct EmptyOnClauseInOnUnimplemented {

View File

@ -35,7 +35,6 @@ extern crate rustc_middle;
#[macro_use] #[macro_use]
extern crate smallvec; extern crate smallvec;
pub mod autoderef;
pub mod errors; pub mod errors;
pub mod infer; pub mod infer;
pub mod solve; pub mod solve;

View File

@ -5,7 +5,6 @@ use super::{
PredicateObligation, PredicateObligation,
}; };
use crate::autoderef::Autoderef;
use crate::infer::InferCtxt; use crate::infer::InferCtxt;
use crate::traits::{NormalizeExt, ObligationCtxt}; use crate::traits::{NormalizeExt, ObligationCtxt};
@ -750,26 +749,30 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
} }
if let ty::Ref(region, base_ty, mutbl) = *real_ty.skip_binder().kind() { if let ty::Ref(region, base_ty, mutbl) = *real_ty.skip_binder().kind() {
let mut autoderef = Autoderef::new( let autoderef = (self.autoderef_steps)(base_ty);
self, if let Some(steps) =
obligation.param_env, autoderef.into_iter().enumerate().find_map(|(steps, (ty, obligations))| {
obligation.cause.body_id, // Re-add the `&`
span, let ty = self.tcx.mk_ref(region, TypeAndMut { ty, mutbl });
base_ty,
);
if let Some(steps) = autoderef.find_map(|(ty, steps)| {
// Re-add the `&`
let ty = self.tcx.mk_ref(region, TypeAndMut { ty, mutbl });
// Remapping bound vars here // Remapping bound vars here
let real_trait_pred_and_ty = let real_trait_pred_and_ty =
real_trait_pred.map_bound(|inner_trait_pred| (inner_trait_pred, ty)); real_trait_pred.map_bound(|inner_trait_pred| (inner_trait_pred, ty));
let obligation = self.mk_trait_obligation_with_new_self_ty( let obligation = self.mk_trait_obligation_with_new_self_ty(
obligation.param_env, obligation.param_env,
real_trait_pred_and_ty, real_trait_pred_and_ty,
); );
Some(steps).filter(|_| self.predicate_may_hold(&obligation)) if obligations
}) { .iter()
.chain([&obligation])
.all(|obligation| self.predicate_may_hold(obligation))
{
Some(steps)
} else {
None
}
})
{
if steps > 0 { if steps > 0 {
// Don't care about `&mut` because `DerefMut` is used less // Don't care about `&mut` because `DerefMut` is used less
// often and user will not expect autoderef happens. // often and user will not expect autoderef happens.