Rollup merge of #106170 - compiler-errors:autoderef-to-analysis, r=lcnr

Move autoderef to `rustc_hir_analysis`

Not sure if this is a change we actually want, but autoderef really is only (functionally) used by `rustc_hir_analysis` and `rustc_hir_typeck`, so it probably should live there.

Instead, implement a separate autoderef helper in `TypeErrCtxt` for the one use-case that  goes against the ordering of the crate graph..
This commit is contained in:
Michael Goulet 2023-01-11 22:25:48 -08:00 committed by GitHub
commit 9928b14772
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
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 =
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_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]`
.label = empty on-clause here

View File

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

View File

@ -1,4 +1,6 @@
use crate::autoderef::Autoderef;
use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter};
use hir::def::DefKind;
use rustc_ast as ast;
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::{Span, DUMMY_SP};
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::outlives_bounds::InferCtxtExt as _;
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;

View File

@ -300,3 +300,15 @@ pub(crate) struct LinkageType {
#[primary_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 astconv;
pub mod autoderef;
mod bounds;
mod check_unused;
mod coherence;

View File

@ -2,11 +2,11 @@
use super::method::MethodCallee;
use super::{FnCtxt, PlaceOp};
use rustc_hir_analysis::autoderef::{Autoderef, AutoderefKind};
use rustc_infer::infer::InferOk;
use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref};
use rustc_middle::ty::{self, Ty};
use rustc_span::Span;
use rustc_trait_selection::autoderef::{Autoderef, AutoderefKind};
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::def::{self, CtorKind, Namespace, Res};
use rustc_hir::def_id::DefId;
use rustc_hir_analysis::autoderef::Autoderef;
use rustc_infer::{
infer,
traits::{self, Obligation},
@ -25,7 +26,6 @@ use rustc_span::def_id::LocalDefId;
use rustc_span::symbol::{sym, Ident};
use rustc_span::Span;
use rustc_target::spec::abi;
use rustc_trait_selection::autoderef::Autoderef;
use rustc_trait_selection::infer::InferCtxtExt as _;
use rustc_trait_selection::traits::error_reporting::DefIdOrName;
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_session::Session;
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 std::cell::{Cell, RefCell};
@ -175,6 +175,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
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_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir_analysis::autoderef::{self, Autoderef};
use rustc_infer::infer::canonical::OriginalQueryValues;
use rustc_infer::infer::canonical::{Canonical, QueryResponse};
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::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::method_autoderef::MethodAutoderefBadTy;
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_errors::Applicability;
use rustc_hir as hir;
use rustc_hir_analysis::autoderef::Autoderef;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_infer::infer::InferOk;
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_span::symbol::{sym, Ident};
use rustc_span::Span;
use rustc_trait_selection::autoderef::Autoderef;
use std::slice;
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::{
IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode,
PredicateObligation,
};
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
@ -91,8 +92,12 @@ pub mod nice_region_error;
pub struct TypeErrCtxt<'a, 'tcx> {
pub infcx: &'a InferCtxt<'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 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<'_, '_> {

View File

@ -688,6 +688,10 @@ impl<'tcx> InferCtxt<'tcx> {
typeck_results: None,
fallback_has_occurred: false,
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_macros::Diagnostic;
use rustc_middle::ty::{self, PolyTraitRef, Ty};
use rustc_session::Limit;
use rustc_span::{Span, Symbol};
#[derive(Diagnostic)]
@ -21,18 +20,6 @@ pub struct UnableToConstructConstantValue<'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)]
#[diag(trait_selection_empty_on_clause_in_rustc_on_unimplemented, code = "E0232")]
pub struct EmptyOnClauseInOnUnimplemented {

View File

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

View File

@ -5,7 +5,6 @@ use super::{
PredicateObligation,
};
use crate::autoderef::Autoderef;
use crate::infer::InferCtxt;
use crate::traits::{NormalizeExt, ObligationCtxt};
@ -750,14 +749,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
}
if let ty::Ref(region, base_ty, mutbl) = *real_ty.skip_binder().kind() {
let mut autoderef = Autoderef::new(
self,
obligation.param_env,
obligation.cause.body_id,
span,
base_ty,
);
if let Some(steps) = autoderef.find_map(|(ty, steps)| {
let autoderef = (self.autoderef_steps)(base_ty);
if let Some(steps) =
autoderef.into_iter().enumerate().find_map(|(steps, (ty, obligations))| {
// Re-add the `&`
let ty = self.tcx.mk_ref(region, TypeAndMut { ty, mutbl });
@ -768,8 +762,17 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
obligation.param_env,
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 {
// Don't care about `&mut` because `DerefMut` is used less
// often and user will not expect autoderef happens.