Auto merge of #99015 - lcnr:fn-ctxt-no-more, r=compiler-errors
stop using `FnCtxt` outside of hir typeck the requirements between **hir typeck**™, and **not hir typeck**™ are different enough to warrant a full split. with this PR `FnCtxt` is now only used for hir typeck (and for one clippy lint which seems to be emulating hir typeck). Once this PR has landed I intend to move `FnCtxt` into a new crate. This should also allow some further general improvements here. r? rust-lang/types
This commit is contained in:
commit
23e21bdd25
20 changed files with 579 additions and 522 deletions
|
@ -181,11 +181,11 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
let generic_ty = type_test.generic_kind.to_ty(self.infcx.tcx);
|
||||
let origin = RelateParamBound(type_test_span, generic_ty, None);
|
||||
self.buffer_error(self.infcx.construct_generic_bound_failure(
|
||||
self.body.source.def_id().expect_local(),
|
||||
type_test_span,
|
||||
Some(origin),
|
||||
type_test.generic_kind,
|
||||
lower_bound_region,
|
||||
self.body.source.def_id().as_local(),
|
||||
));
|
||||
} else {
|
||||
// FIXME. We should handle this case better. It
|
||||
|
|
|
@ -63,7 +63,7 @@ use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString, Mul
|
|||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_hir::{Item, ItemKind, Node};
|
||||
use rustc_hir::Node;
|
||||
use rustc_middle::dep_graph::DepContext;
|
||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||
use rustc_middle::ty::{
|
||||
|
@ -348,7 +348,11 @@ pub fn same_type_modulo_infer<'tcx>(a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
|
|||
}
|
||||
|
||||
impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
pub fn report_region_errors(&self, errors: &[RegionResolutionError<'tcx>]) {
|
||||
pub fn report_region_errors(
|
||||
&self,
|
||||
generic_param_scope: LocalDefId,
|
||||
errors: &[RegionResolutionError<'tcx>],
|
||||
) {
|
||||
debug!("report_region_errors(): {} errors to start", errors.len());
|
||||
|
||||
// try to pre-process the errors, which will group some of them
|
||||
|
@ -379,6 +383,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
|
||||
RegionResolutionError::GenericBoundFailure(origin, param_ty, sub) => {
|
||||
self.report_generic_bound_failure(
|
||||
generic_param_scope,
|
||||
origin.span(),
|
||||
Some(origin),
|
||||
param_ty,
|
||||
|
@ -2269,56 +2274,30 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
|
||||
pub fn report_generic_bound_failure(
|
||||
&self,
|
||||
generic_param_scope: LocalDefId,
|
||||
span: Span,
|
||||
origin: Option<SubregionOrigin<'tcx>>,
|
||||
bound_kind: GenericKind<'tcx>,
|
||||
sub: Region<'tcx>,
|
||||
) {
|
||||
let owner =
|
||||
self.in_progress_typeck_results.map(|typeck_results| typeck_results.borrow().hir_owner);
|
||||
self.construct_generic_bound_failure(span, origin, bound_kind, sub, owner).emit();
|
||||
self.construct_generic_bound_failure(generic_param_scope, span, origin, bound_kind, sub)
|
||||
.emit();
|
||||
}
|
||||
|
||||
pub fn construct_generic_bound_failure(
|
||||
&self,
|
||||
generic_param_scope: LocalDefId,
|
||||
span: Span,
|
||||
origin: Option<SubregionOrigin<'tcx>>,
|
||||
bound_kind: GenericKind<'tcx>,
|
||||
sub: Region<'tcx>,
|
||||
owner: Option<LocalDefId>,
|
||||
) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
|
||||
let hir = self.tcx.hir();
|
||||
// Attempt to obtain the span of the parameter so we can
|
||||
// suggest adding an explicit lifetime bound to it.
|
||||
let generics = owner.map(|owner| {
|
||||
let hir_id = hir.local_def_id_to_hir_id(owner);
|
||||
let parent_id = hir.get_parent_item(hir_id);
|
||||
(
|
||||
// Parent item could be a `mod`, so we check the HIR before calling:
|
||||
if let Some(Node::Item(Item {
|
||||
kind: ItemKind::Trait(..) | ItemKind::Impl { .. },
|
||||
..
|
||||
})) = hir.find_by_def_id(parent_id)
|
||||
{
|
||||
Some(self.tcx.generics_of(parent_id))
|
||||
} else {
|
||||
None
|
||||
},
|
||||
self.tcx.generics_of(owner.to_def_id()),
|
||||
hir.span(hir_id),
|
||||
)
|
||||
});
|
||||
|
||||
let span = match generics {
|
||||
// This is to get around the trait identity obligation, that has a `DUMMY_SP` as signal
|
||||
// for other diagnostics, so we need to recover it here.
|
||||
Some((_, _, node)) if span.is_dummy() => node,
|
||||
_ => span,
|
||||
};
|
||||
|
||||
let generics = self.tcx.generics_of(generic_param_scope);
|
||||
// type_param_span is (span, has_bounds)
|
||||
let type_param_span = match (generics, bound_kind) {
|
||||
(Some((_, ref generics, _)), GenericKind::Param(ref param)) => {
|
||||
let type_param_span = match bound_kind {
|
||||
GenericKind::Param(ref param) => {
|
||||
// Account for the case where `param` corresponds to `Self`,
|
||||
// which doesn't have the expected type argument.
|
||||
if !(generics.has_self && param.index == 0) {
|
||||
|
@ -2346,30 +2325,23 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
}
|
||||
_ => None,
|
||||
};
|
||||
let new_lt = generics
|
||||
.as_ref()
|
||||
.and_then(|(parent_g, g, _)| {
|
||||
let mut possible = (b'a'..=b'z').map(|c| format!("'{}", c as char));
|
||||
let mut lts_names = g
|
||||
.params
|
||||
.iter()
|
||||
|
||||
let new_lt = {
|
||||
let mut possible = (b'a'..=b'z').map(|c| format!("'{}", c as char));
|
||||
let lts_names =
|
||||
iter::successors(Some(generics), |g| g.parent.map(|p| self.tcx.generics_of(p)))
|
||||
.flat_map(|g| &g.params)
|
||||
.filter(|p| matches!(p.kind, ty::GenericParamDefKind::Lifetime))
|
||||
.map(|p| p.name.as_str())
|
||||
.collect::<Vec<_>>();
|
||||
if let Some(g) = parent_g {
|
||||
lts_names.extend(
|
||||
g.params
|
||||
.iter()
|
||||
.filter(|p| matches!(p.kind, ty::GenericParamDefKind::Lifetime))
|
||||
.map(|p| p.name.as_str()),
|
||||
);
|
||||
}
|
||||
possible.find(|candidate| !lts_names.contains(&&candidate[..]))
|
||||
})
|
||||
.unwrap_or("'lt".to_string());
|
||||
possible
|
||||
.find(|candidate| !lts_names.contains(&&candidate[..]))
|
||||
.unwrap_or("'lt".to_string())
|
||||
};
|
||||
|
||||
let add_lt_sugg = generics
|
||||
.as_ref()
|
||||
.and_then(|(_, g, _)| g.params.first())
|
||||
.params
|
||||
.first()
|
||||
.and_then(|param| param.def_id.as_local())
|
||||
.map(|def_id| (self.tcx.def_span(def_id).shrink_to_lo(), format!("{}, ", new_lt)));
|
||||
|
||||
|
@ -2571,7 +2543,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
);
|
||||
if let Some(infer::RelateParamBound(_, t, _)) = origin {
|
||||
let return_impl_trait =
|
||||
owner.and_then(|owner| self.tcx.return_type_impl_trait(owner)).is_some();
|
||||
self.tcx.return_type_impl_trait(generic_param_scope).is_some();
|
||||
let t = self.resolve_vars_if_possible(t);
|
||||
match t.kind() {
|
||||
// We've got:
|
||||
|
|
|
@ -1301,7 +1301,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
/// result. After this, no more unification operations should be
|
||||
/// done -- or the compiler will panic -- but it is legal to use
|
||||
/// `resolve_vars_if_possible` as well as `fully_resolve`.
|
||||
pub fn resolve_regions_and_report_errors(&self, outlives_env: &OutlivesEnvironment<'tcx>) {
|
||||
pub fn resolve_regions_and_report_errors(
|
||||
&self,
|
||||
generic_param_scope: LocalDefId,
|
||||
outlives_env: &OutlivesEnvironment<'tcx>,
|
||||
) {
|
||||
let errors = self.resolve_regions(outlives_env);
|
||||
|
||||
if !self.is_tainted_by_errors() {
|
||||
|
@ -1310,7 +1314,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
// this infcx was in use. This is totally hokey but
|
||||
// otherwise we have a hard time separating legit region
|
||||
// errors from silly ones.
|
||||
self.report_region_errors(&errors);
|
||||
self.report_region_errors(generic_param_scope, &errors);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -68,6 +68,7 @@ use crate::infer::{
|
|||
};
|
||||
use crate::traits::{ObligationCause, ObligationCauseCode};
|
||||
use rustc_data_structures::undo_log::UndoLogs;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_middle::ty::subst::GenericArgKind;
|
||||
use rustc_middle::ty::{self, Region, Ty, TyCtxt, TypeVisitable};
|
||||
use smallvec::smallvec;
|
||||
|
@ -163,6 +164,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
|
|||
|
||||
pub fn check_region_obligations_and_report_errors(
|
||||
&self,
|
||||
generic_param_scope: LocalDefId,
|
||||
outlives_env: &OutlivesEnvironment<'tcx>,
|
||||
) {
|
||||
self.process_registered_region_obligations(
|
||||
|
@ -170,7 +172,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
|
|||
outlives_env.param_env,
|
||||
);
|
||||
|
||||
self.resolve_regions_and_report_errors(outlives_env)
|
||||
self.resolve_regions_and_report_errors(generic_param_scope, outlives_env)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,22 @@
|
|||
use rustc_middle::ty::TyCtxt;
|
||||
use std::cell::RefCell;
|
||||
|
||||
use super::TraitEngine;
|
||||
use super::{ChalkFulfillmentContext, FulfillmentContext};
|
||||
use crate::infer::InferCtxtExt;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_infer::infer::{InferCtxt, InferOk};
|
||||
use rustc_infer::traits::{
|
||||
FulfillmentError, Obligation, ObligationCause, PredicateObligation, TraitEngineExt as _,
|
||||
};
|
||||
use rustc_middle::ty::error::TypeError;
|
||||
use rustc_middle::ty::ToPredicate;
|
||||
use rustc_middle::ty::TypeFoldable;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
|
||||
pub trait TraitEngineExt<'tcx> {
|
||||
fn new(tcx: TyCtxt<'tcx>) -> Box<Self>;
|
||||
|
||||
fn new_ignoring_regions(tcx: TyCtxt<'tcx>) -> Box<Self>;
|
||||
}
|
||||
|
||||
impl<'tcx> TraitEngineExt<'tcx> for dyn TraitEngine<'tcx> {
|
||||
|
@ -15,4 +27,96 @@ impl<'tcx> TraitEngineExt<'tcx> for dyn TraitEngine<'tcx> {
|
|||
Box::new(FulfillmentContext::new())
|
||||
}
|
||||
}
|
||||
|
||||
fn new_ignoring_regions(tcx: TyCtxt<'tcx>) -> Box<Self> {
|
||||
if tcx.sess.opts.unstable_opts.chalk {
|
||||
Box::new(ChalkFulfillmentContext::new())
|
||||
} else {
|
||||
Box::new(FulfillmentContext::new_ignoring_regions())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Used if you want to have pleasant experience when dealing
|
||||
/// with obligations outside of hir or mir typeck.
|
||||
pub struct ObligationCtxt<'a, 'tcx> {
|
||||
pub infcx: &'a InferCtxt<'a, 'tcx>,
|
||||
engine: RefCell<Box<dyn TraitEngine<'tcx>>>,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
|
||||
pub fn new(infcx: &'a InferCtxt<'a, 'tcx>) -> Self {
|
||||
Self { infcx, engine: RefCell::new(<dyn TraitEngine<'_>>::new(infcx.tcx)) }
|
||||
}
|
||||
|
||||
pub fn register_obligation(&self, obligation: PredicateObligation<'tcx>) {
|
||||
self.engine.borrow_mut().register_predicate_obligation(self.infcx, obligation);
|
||||
}
|
||||
|
||||
pub fn register_obligations(
|
||||
&self,
|
||||
obligations: impl IntoIterator<Item = PredicateObligation<'tcx>>,
|
||||
) {
|
||||
// Can't use `register_predicate_obligations` because the iterator
|
||||
// may also use this `ObligationCtxt`.
|
||||
for obligation in obligations {
|
||||
self.engine.borrow_mut().register_predicate_obligation(self.infcx, obligation)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn register_infer_ok_obligations<T>(&self, infer_ok: InferOk<'tcx, T>) -> T {
|
||||
let InferOk { value, obligations } = infer_ok;
|
||||
self.engine.borrow_mut().register_predicate_obligations(self.infcx, obligations);
|
||||
value
|
||||
}
|
||||
|
||||
/// Requires that `ty` must implement the trait with `def_id` in
|
||||
/// the given environment. This trait must not have any type
|
||||
/// parameters (except for `Self`).
|
||||
pub fn register_bound(
|
||||
&self,
|
||||
cause: ObligationCause<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
def_id: DefId,
|
||||
) {
|
||||
let tcx = self.infcx.tcx;
|
||||
let trait_ref = ty::TraitRef { def_id, substs: tcx.mk_substs_trait(ty, &[]) };
|
||||
self.register_obligation(Obligation {
|
||||
cause,
|
||||
recursion_depth: 0,
|
||||
param_env,
|
||||
predicate: ty::Binder::dummy(trait_ref).without_const().to_predicate(tcx),
|
||||
});
|
||||
}
|
||||
|
||||
pub fn normalize<T: TypeFoldable<'tcx>>(
|
||||
&self,
|
||||
cause: ObligationCause<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
value: T,
|
||||
) -> T {
|
||||
let infer_ok = self.infcx.partially_normalize_associated_types_in(cause, param_env, value);
|
||||
self.register_infer_ok_obligations(infer_ok)
|
||||
}
|
||||
|
||||
pub fn equate_types(
|
||||
&self,
|
||||
cause: &ObligationCause<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
expected: Ty<'tcx>,
|
||||
actual: Ty<'tcx>,
|
||||
) -> Result<(), TypeError<'tcx>> {
|
||||
match self.infcx.at(cause, param_env).eq(expected, actual) {
|
||||
Ok(InferOk { obligations, value: () }) => {
|
||||
self.register_obligations(obligations);
|
||||
Ok(())
|
||||
}
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn select_all_or_error(&self) -> Vec<FulfillmentError<'tcx>> {
|
||||
self.engine.borrow_mut().select_all_or_error(self.infcx)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ pub use self::SelectionError::*;
|
|||
|
||||
pub use self::coherence::{add_placeholder_note, orphan_check, overlapping_impls};
|
||||
pub use self::coherence::{OrphanCheckErr, OverlapResult};
|
||||
pub use self::engine::TraitEngineExt;
|
||||
pub use self::engine::{ObligationCtxt, TraitEngineExt};
|
||||
pub use self::fulfill::{FulfillmentContext, PendingPredicateObligation};
|
||||
pub use self::object_safety::astconv_object_safety_violations;
|
||||
pub use self::object_safety::is_vtable_safe_method;
|
||||
|
@ -237,29 +237,37 @@ fn do_normalize_predicates<'tcx>(
|
|||
// cares about declarations like `'a: 'b`.
|
||||
let outlives_env = OutlivesEnvironment::new(elaborated_env);
|
||||
|
||||
infcx.resolve_regions_and_report_errors(&outlives_env);
|
||||
// FIXME: It's very weird that we ignore region obligations but apparently
|
||||
// still need to use `resolve_regions` as we need the resolved regions in
|
||||
// the normalized predicates.
|
||||
let errors = infcx.resolve_regions(&outlives_env);
|
||||
if !errors.is_empty() {
|
||||
tcx.sess.delay_span_bug(
|
||||
span,
|
||||
format!(
|
||||
"failed region resolution while normalizing {elaborated_env:?}: {errors:?}"
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
let predicates = match infcx.fully_resolve(predicates) {
|
||||
Ok(predicates) => predicates,
|
||||
match infcx.fully_resolve(predicates) {
|
||||
Ok(predicates) => Ok(predicates),
|
||||
Err(fixup_err) => {
|
||||
// If we encounter a fixup error, it means that some type
|
||||
// variable wound up unconstrained. I actually don't know
|
||||
// if this can happen, and I certainly don't expect it to
|
||||
// happen often, but if it did happen it probably
|
||||
// represents a legitimate failure due to some kind of
|
||||
// unconstrained variable, and it seems better not to ICE,
|
||||
// all things considered.
|
||||
let reported = tcx.sess.span_err(span, &fixup_err.to_string());
|
||||
return Err(reported);
|
||||
// unconstrained variable.
|
||||
//
|
||||
// @lcnr: Let's still ICE here for now. I want a test case
|
||||
// for that.
|
||||
span_bug!(
|
||||
span,
|
||||
"inference variables in normalized parameter environment: {}",
|
||||
fixup_err
|
||||
);
|
||||
}
|
||||
};
|
||||
if predicates.needs_infer() {
|
||||
let reported = tcx
|
||||
.sess
|
||||
.delay_span_bug(span, "encountered inference variables after `fully_resolve`");
|
||||
Err(reported)
|
||||
} else {
|
||||
Ok(predicates)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -254,7 +254,7 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
|
|||
let result = tcx.normalize_projection_ty(c_data)?;
|
||||
// We don't expect ambiguity.
|
||||
if result.is_ambiguous() {
|
||||
return Err(NoSolution);
|
||||
bug!("unexpected ambiguity: {:?} {:?}", c_data, result);
|
||||
}
|
||||
let InferOk { value: result, obligations } =
|
||||
self.infcx.instantiate_query_response_and_region_obligations(
|
||||
|
@ -293,7 +293,7 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
|
|||
let result = tcx.normalize_projection_ty(c_data)?;
|
||||
// We don't expect ambiguity.
|
||||
if result.is_ambiguous() {
|
||||
return Err(NoSolution);
|
||||
bug!("unexpected ambiguity: {:?} {:?}", c_data, result);
|
||||
}
|
||||
let InferOk { value: result, obligations } =
|
||||
self.infcx.instantiate_query_response_and_region_obligations(
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
use crate::check::wfcheck::for_item;
|
||||
use crate::check::intrinsicck::InlineAsmCtxt;
|
||||
|
||||
use super::coercion::CoerceMany;
|
||||
use super::compare_method::check_type_bounds;
|
||||
use super::compare_method::{compare_const_impl, compare_impl_method, compare_ty_impl};
|
||||
use super::*;
|
||||
|
||||
use rustc_attr as attr;
|
||||
use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan};
|
||||
use rustc_hir as hir;
|
||||
|
@ -29,8 +28,8 @@ use rustc_session::lint::builtin::{UNINHABITED_STATIC, UNSUPPORTED_CALLING_CONVE
|
|||
use rustc_span::symbol::sym;
|
||||
use rustc_span::{self, Span};
|
||||
use rustc_target::spec::abi::Abi;
|
||||
use rustc_trait_selection::traits;
|
||||
use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
|
||||
use rustc_trait_selection::traits::{self, ObligationCtxt};
|
||||
use rustc_ty_utils::representability::{self, Representability};
|
||||
|
||||
use std::iter;
|
||||
|
@ -733,14 +732,13 @@ fn check_opaque_meets_bounds<'tcx>(
|
|||
let param_env = tcx.param_env(defining_use_anchor);
|
||||
|
||||
tcx.infer_ctxt().with_opaque_type_inference(defining_use_anchor).enter(move |infcx| {
|
||||
let inh = Inherited::new(infcx, def_id);
|
||||
let infcx = &inh.infcx;
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
let opaque_ty = tcx.mk_opaque(def_id.to_def_id(), substs);
|
||||
|
||||
let misc_cause = traits::ObligationCause::misc(span, hir_id);
|
||||
|
||||
match infcx.at(&misc_cause, param_env).eq(opaque_ty, hidden_type) {
|
||||
Ok(infer_ok) => inh.register_infer_ok_obligations(infer_ok),
|
||||
Ok(infer_ok) => ocx.register_infer_ok_obligations(infer_ok),
|
||||
Err(ty_err) => {
|
||||
tcx.sess.delay_span_bug(
|
||||
span,
|
||||
|
@ -754,11 +752,11 @@ fn check_opaque_meets_bounds<'tcx>(
|
|||
// hidden type is well formed even without those bounds.
|
||||
let predicate =
|
||||
ty::Binder::dummy(ty::PredicateKind::WellFormed(hidden_type.into())).to_predicate(tcx);
|
||||
inh.register_predicate(Obligation::new(misc_cause, param_env, predicate));
|
||||
ocx.register_obligation(Obligation::new(misc_cause, param_env, predicate));
|
||||
|
||||
// Check that all obligations are satisfied by the implementation's
|
||||
// version.
|
||||
let errors = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx);
|
||||
let errors = ocx.select_all_or_error();
|
||||
if !errors.is_empty() {
|
||||
infcx.report_fulfillment_errors(&errors, None, false);
|
||||
}
|
||||
|
@ -769,7 +767,10 @@ fn check_opaque_meets_bounds<'tcx>(
|
|||
// Can have different predicates to their defining use
|
||||
hir::OpaqueTyOrigin::TyAlias => {
|
||||
let outlives_environment = OutlivesEnvironment::new(param_env);
|
||||
infcx.check_region_obligations_and_report_errors(&outlives_environment);
|
||||
infcx.check_region_obligations_and_report_errors(
|
||||
defining_use_anchor,
|
||||
&outlives_environment,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -940,10 +941,7 @@ fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) {
|
|||
DefKind::GlobalAsm => {
|
||||
let it = tcx.hir().item(id);
|
||||
let hir::ItemKind::GlobalAsm(asm) = it.kind else { span_bug!(it.span, "DefKind::GlobalAsm but got {:#?}", it) };
|
||||
for_item(tcx, it).with_fcx(|fcx| {
|
||||
fcx.check_asm(asm, it.hir_id());
|
||||
Default::default()
|
||||
})
|
||||
InlineAsmCtxt::new_global_asm(tcx).check_asm(asm, id.hir_id());
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
use super::potentially_plural_count;
|
||||
use crate::check::regionck::OutlivesEnvironmentExt;
|
||||
use crate::check::wfcheck;
|
||||
use crate::errors::LifetimesOrBoundsMismatchOnTrait;
|
||||
use rustc_data_structures::stable_set::FxHashSet;
|
||||
use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId, ErrorGuaranteed};
|
||||
|
@ -7,7 +9,7 @@ use rustc_hir::def::{DefKind, Res};
|
|||
use rustc_hir::intravisit;
|
||||
use rustc_hir::{GenericParamKind, ImplItemKind, TraitItemKind};
|
||||
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
|
||||
use rustc_infer::infer::{self, InferOk, TyCtxtInferExt};
|
||||
use rustc_infer::infer::{self, TyCtxtInferExt};
|
||||
use rustc_infer::traits::util;
|
||||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||
use rustc_middle::ty::subst::{InternalSubsts, Subst};
|
||||
|
@ -16,11 +18,11 @@ use rustc_middle::ty::{self, DefIdTree};
|
|||
use rustc_middle::ty::{GenericParamDefKind, ToPredicate, TyCtxt};
|
||||
use rustc_span::Span;
|
||||
use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
|
||||
use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode, Reveal};
|
||||
use rustc_trait_selection::traits::{
|
||||
self, ObligationCause, ObligationCauseCode, ObligationCtxt, Reveal,
|
||||
};
|
||||
use std::iter;
|
||||
|
||||
use super::{potentially_plural_count, FnCtxt, Inherited};
|
||||
|
||||
/// Checks that a method from an impl conforms to the signature of
|
||||
/// the same method as declared in the trait.
|
||||
///
|
||||
|
@ -205,21 +207,19 @@ fn compare_predicate_entailment<'tcx>(
|
|||
);
|
||||
let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause);
|
||||
|
||||
tcx.infer_ctxt().enter(|infcx| {
|
||||
let inh = Inherited::new(infcx, impl_m.def_id.expect_local());
|
||||
let infcx = &inh.infcx;
|
||||
tcx.infer_ctxt().enter(|ref infcx| {
|
||||
let ocx = ObligationCtxt::new(infcx);
|
||||
|
||||
debug!("compare_impl_method: caller_bounds={:?}", param_env.caller_bounds());
|
||||
|
||||
let mut selcx = traits::SelectionContext::new(&infcx);
|
||||
|
||||
let impl_m_own_bounds = impl_m_predicates.instantiate_own(tcx, impl_to_placeholder_substs);
|
||||
for (predicate, span) in iter::zip(impl_m_own_bounds.predicates, impl_m_own_bounds.spans) {
|
||||
let normalize_cause = traits::ObligationCause::misc(span, impl_m_hir_id);
|
||||
let traits::Normalized { value: predicate, obligations } =
|
||||
traits::normalize(&mut selcx, param_env, normalize_cause, predicate);
|
||||
|
||||
inh.register_predicates(obligations);
|
||||
ocx.register_obligations(obligations);
|
||||
let cause = ObligationCause::new(
|
||||
span,
|
||||
impl_m_hir_id,
|
||||
|
@ -228,7 +228,7 @@ fn compare_predicate_entailment<'tcx>(
|
|||
trait_item_def_id: trait_m.def_id,
|
||||
},
|
||||
);
|
||||
inh.register_predicate(traits::Obligation::new(cause, param_env, predicate));
|
||||
ocx.register_obligation(traits::Obligation::new(cause, param_env, predicate));
|
||||
}
|
||||
|
||||
// We now need to check that the signature of the impl method is
|
||||
|
@ -254,32 +254,31 @@ fn compare_predicate_entailment<'tcx>(
|
|||
infer::HigherRankedType,
|
||||
tcx.fn_sig(impl_m.def_id),
|
||||
);
|
||||
let impl_sig =
|
||||
inh.normalize_associated_types_in(impl_m_span, impl_m_hir_id, param_env, impl_sig);
|
||||
|
||||
let norm_cause = ObligationCause::misc(impl_m_span, impl_m_hir_id);
|
||||
let impl_sig = ocx.normalize(norm_cause.clone(), param_env, impl_sig);
|
||||
let impl_fty = tcx.mk_fn_ptr(ty::Binder::dummy(impl_sig));
|
||||
debug!("compare_impl_method: impl_fty={:?}", impl_fty);
|
||||
|
||||
let trait_sig = tcx.bound_fn_sig(trait_m.def_id).subst(tcx, trait_to_placeholder_substs);
|
||||
let trait_sig = tcx.liberate_late_bound_regions(impl_m.def_id, trait_sig);
|
||||
let trait_sig =
|
||||
inh.normalize_associated_types_in(impl_m_span, impl_m_hir_id, param_env, trait_sig);
|
||||
let trait_sig = ocx.normalize(norm_cause, param_env, trait_sig);
|
||||
// Add the resulting inputs and output as well-formed.
|
||||
wf_tys.extend(trait_sig.inputs_and_output.iter());
|
||||
let trait_fty = tcx.mk_fn_ptr(ty::Binder::dummy(trait_sig));
|
||||
|
||||
debug!("compare_impl_method: trait_fty={:?}", trait_fty);
|
||||
|
||||
let sub_result = infcx.at(&cause, param_env).sup(trait_fty, impl_fty).map(
|
||||
|InferOk { obligations, .. }| {
|
||||
// FIXME: We'd want to keep more accurate spans than "the method signature" when
|
||||
// processing the comparison between the trait and impl fn, but we sadly lose them
|
||||
// and point at the whole signature when a trait bound or specific input or output
|
||||
// type would be more appropriate. In other places we have a `Vec<Span>`
|
||||
// corresponding to their `Vec<Predicate>`, but we don't have that here.
|
||||
// Fixing this would improve the output of test `issue-83765.rs`.
|
||||
inh.register_predicates(obligations);
|
||||
},
|
||||
);
|
||||
// FIXME: We'd want to keep more accurate spans than "the method signature" when
|
||||
// processing the comparison between the trait and impl fn, but we sadly lose them
|
||||
// and point at the whole signature when a trait bound or specific input or output
|
||||
// type would be more appropriate. In other places we have a `Vec<Span>`
|
||||
// corresponding to their `Vec<Predicate>`, but we don't have that here.
|
||||
// Fixing this would improve the output of test `issue-83765.rs`.
|
||||
let sub_result = infcx
|
||||
.at(&cause, param_env)
|
||||
.sup(trait_fty, impl_fty)
|
||||
.map(|infer_ok| ocx.register_infer_ok_obligations(infer_ok));
|
||||
|
||||
if let Err(terr) = sub_result {
|
||||
debug!("sub_types failed: impl ty {:?}, trait ty {:?}", impl_fty, trait_fty);
|
||||
|
@ -385,7 +384,7 @@ fn compare_predicate_entailment<'tcx>(
|
|||
|
||||
// Check that all obligations are satisfied by the implementation's
|
||||
// version.
|
||||
let errors = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx);
|
||||
let errors = ocx.select_all_or_error();
|
||||
if !errors.is_empty() {
|
||||
let reported = infcx.report_fulfillment_errors(&errors, None, false);
|
||||
return Err(reported);
|
||||
|
@ -395,7 +394,10 @@ fn compare_predicate_entailment<'tcx>(
|
|||
// lifetime parameters.
|
||||
let mut outlives_environment = OutlivesEnvironment::new(param_env);
|
||||
outlives_environment.add_implied_bounds(infcx, wf_tys, impl_m_hir_id);
|
||||
infcx.check_region_obligations_and_report_errors(&outlives_environment);
|
||||
infcx.check_region_obligations_and_report_errors(
|
||||
impl_m.def_id.expect_local(),
|
||||
&outlives_environment,
|
||||
);
|
||||
|
||||
Ok(())
|
||||
})
|
||||
|
@ -1058,8 +1060,7 @@ pub(crate) fn compare_const_impl<'tcx>(
|
|||
|
||||
tcx.infer_ctxt().enter(|infcx| {
|
||||
let param_env = tcx.param_env(impl_c.def_id);
|
||||
let inh = Inherited::new(infcx, impl_c.def_id.expect_local());
|
||||
let infcx = &inh.infcx;
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
|
||||
// The below is for the most part highly similar to the procedure
|
||||
// for methods above. It is simpler in many respects, especially
|
||||
|
@ -1082,20 +1083,18 @@ pub(crate) fn compare_const_impl<'tcx>(
|
|||
);
|
||||
|
||||
// There is no "body" here, so just pass dummy id.
|
||||
let impl_ty =
|
||||
inh.normalize_associated_types_in(impl_c_span, impl_c_hir_id, param_env, impl_ty);
|
||||
let impl_ty = ocx.normalize(cause.clone(), param_env, impl_ty);
|
||||
|
||||
debug!("compare_const_impl: impl_ty={:?}", impl_ty);
|
||||
|
||||
let trait_ty =
|
||||
inh.normalize_associated_types_in(impl_c_span, impl_c_hir_id, param_env, trait_ty);
|
||||
let trait_ty = ocx.normalize(cause.clone(), param_env, trait_ty);
|
||||
|
||||
debug!("compare_const_impl: trait_ty={:?}", trait_ty);
|
||||
|
||||
let err = infcx
|
||||
.at(&cause, param_env)
|
||||
.sup(trait_ty, impl_ty)
|
||||
.map(|ok| inh.register_infer_ok_obligations(ok));
|
||||
.map(|ok| ocx.register_infer_ok_obligations(ok));
|
||||
|
||||
if let Err(terr) = err {
|
||||
debug!(
|
||||
|
@ -1142,14 +1141,15 @@ pub(crate) fn compare_const_impl<'tcx>(
|
|||
|
||||
// Check that all obligations are satisfied by the implementation's
|
||||
// version.
|
||||
let errors = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx);
|
||||
let errors = ocx.select_all_or_error();
|
||||
if !errors.is_empty() {
|
||||
infcx.report_fulfillment_errors(&errors, None, false);
|
||||
return;
|
||||
}
|
||||
|
||||
let outlives_environment = OutlivesEnvironment::new(param_env);
|
||||
infcx.resolve_regions_and_report_errors(&outlives_environment);
|
||||
infcx
|
||||
.resolve_regions_and_report_errors(impl_c.def_id.expect_local(), &outlives_environment);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1241,8 +1241,7 @@ fn compare_type_predicate_entailment<'tcx>(
|
|||
);
|
||||
let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause.clone());
|
||||
tcx.infer_ctxt().enter(|infcx| {
|
||||
let inh = Inherited::new(infcx, impl_ty.def_id.expect_local());
|
||||
let infcx = &inh.infcx;
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
|
||||
debug!("compare_type_predicate_entailment: caller_bounds={:?}", param_env.caller_bounds());
|
||||
|
||||
|
@ -1252,13 +1251,13 @@ fn compare_type_predicate_entailment<'tcx>(
|
|||
let traits::Normalized { value: predicate, obligations } =
|
||||
traits::normalize(&mut selcx, param_env, normalize_cause.clone(), predicate);
|
||||
|
||||
inh.register_predicates(obligations);
|
||||
inh.register_predicate(traits::Obligation::new(cause.clone(), param_env, predicate));
|
||||
ocx.register_obligations(obligations);
|
||||
ocx.register_obligation(traits::Obligation::new(cause.clone(), param_env, predicate));
|
||||
}
|
||||
|
||||
// Check that all obligations are satisfied by the implementation's
|
||||
// version.
|
||||
let errors = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx);
|
||||
let errors = ocx.select_all_or_error();
|
||||
if !errors.is_empty() {
|
||||
let reported = infcx.report_fulfillment_errors(&errors, None, false);
|
||||
return Err(reported);
|
||||
|
@ -1267,7 +1266,10 @@ fn compare_type_predicate_entailment<'tcx>(
|
|||
// Finally, resolve all regions. This catches wily misuses of
|
||||
// lifetime parameters.
|
||||
let outlives_environment = OutlivesEnvironment::new(param_env);
|
||||
infcx.check_region_obligations_and_report_errors(&outlives_environment);
|
||||
infcx.check_region_obligations_and_report_errors(
|
||||
impl_ty.def_id.expect_local(),
|
||||
&outlives_environment,
|
||||
);
|
||||
|
||||
Ok(())
|
||||
})
|
||||
|
@ -1431,10 +1433,9 @@ pub fn check_type_bounds<'tcx>(
|
|||
impl_ty_substs.rebase_onto(tcx, impl_ty.container.id(), impl_trait_ref.substs);
|
||||
|
||||
tcx.infer_ctxt().enter(move |infcx| {
|
||||
let inh = Inherited::new(infcx, impl_ty.def_id.expect_local());
|
||||
let infcx = &inh.infcx;
|
||||
let mut selcx = traits::SelectionContext::new(&infcx);
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
|
||||
let mut selcx = traits::SelectionContext::new(&infcx);
|
||||
let impl_ty_hir_id = tcx.hir().local_def_id_to_hir_id(impl_ty.def_id.expect_local());
|
||||
let normalize_cause = ObligationCause::new(
|
||||
impl_ty_span,
|
||||
|
@ -1477,13 +1478,13 @@ pub fn check_type_bounds<'tcx>(
|
|||
debug!("compare_projection_bounds: normalized predicate = {:?}", normalized_predicate);
|
||||
obligation.predicate = normalized_predicate;
|
||||
|
||||
inh.register_predicates(obligations);
|
||||
inh.register_predicate(obligation);
|
||||
ocx.register_obligations(obligations);
|
||||
ocx.register_obligation(obligation);
|
||||
}
|
||||
|
||||
// Check that all obligations are satisfied by the implementation's
|
||||
// version.
|
||||
let errors = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx);
|
||||
let errors = ocx.select_all_or_error();
|
||||
if !errors.is_empty() {
|
||||
let reported = infcx.report_fulfillment_errors(&errors, None, false);
|
||||
return Err(reported);
|
||||
|
@ -1491,16 +1492,18 @@ pub fn check_type_bounds<'tcx>(
|
|||
|
||||
// Finally, resolve all regions. This catches wily misuses of
|
||||
// lifetime parameters.
|
||||
//
|
||||
// FIXME: Remove that `FnCtxt`.
|
||||
let fcx = FnCtxt::new(&inh, param_env, impl_ty_hir_id);
|
||||
let implied_bounds = match impl_ty.container {
|
||||
ty::TraitContainer(_) => FxHashSet::default(),
|
||||
ty::ImplContainer(def_id) => fcx.impl_implied_bounds(def_id, impl_ty_span),
|
||||
ty::ImplContainer(def_id) => {
|
||||
wfcheck::impl_implied_bounds(tcx, param_env, def_id.expect_local(), impl_ty_span)
|
||||
}
|
||||
};
|
||||
let mut outlives_environment = OutlivesEnvironment::new(param_env);
|
||||
outlives_environment.add_implied_bounds(infcx, implied_bounds, impl_ty_hir_id);
|
||||
infcx.check_region_obligations_and_report_errors(&outlives_environment);
|
||||
outlives_environment.add_implied_bounds(&infcx, implied_bounds, impl_ty_hir_id);
|
||||
infcx.check_region_obligations_and_report_errors(
|
||||
impl_ty.def_id.expect_local(),
|
||||
&outlives_environment,
|
||||
);
|
||||
|
||||
Ok(())
|
||||
})
|
||||
|
|
|
@ -37,7 +37,6 @@ use rustc_trait_selection::infer::InferCtxtExt as _;
|
|||
use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
|
||||
use rustc_trait_selection::traits::{
|
||||
self, ObligationCause, ObligationCauseCode, StatementAsExpression, TraitEngine, TraitEngineExt,
|
||||
WellFormedLoc,
|
||||
};
|
||||
|
||||
use std::collections::hash_map::Entry;
|
||||
|
@ -375,29 +374,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
(result, spans)
|
||||
}
|
||||
|
||||
/// Convenience method which tracks extra diagnostic information for normalization
|
||||
/// that occurs as a result of WF checking. The `hir_id` is the `HirId` of the hir item
|
||||
/// whose type is being wf-checked - this is used to construct a more precise span if
|
||||
/// an error occurs.
|
||||
///
|
||||
/// It is never necessary to call this method - calling `normalize_associated_types_in` will
|
||||
/// just result in a slightly worse diagnostic span, and will still be sound.
|
||||
pub(in super::super) fn normalize_associated_types_in_wf<T>(
|
||||
&self,
|
||||
span: Span,
|
||||
value: T,
|
||||
loc: WellFormedLoc,
|
||||
) -> T
|
||||
where
|
||||
T: TypeFoldable<'tcx>,
|
||||
{
|
||||
self.inh.normalize_associated_types_in_with_cause(
|
||||
ObligationCause::new(span, self.body_id, ObligationCauseCode::WellFormed(Some(loc))),
|
||||
self.param_env,
|
||||
value,
|
||||
)
|
||||
}
|
||||
|
||||
pub(in super::super) fn normalize_associated_types_in<T>(&self, span: Span, value: T) -> T
|
||||
where
|
||||
T: TypeFoldable<'tcx>,
|
||||
|
|
|
@ -4,6 +4,7 @@ use crate::check::fn_ctxt::arg_matrix::{
|
|||
ArgMatrix, Compatibility, Error, ExpectedIdx, ProvidedIdx,
|
||||
};
|
||||
use crate::check::gather_locals::Declaration;
|
||||
use crate::check::intrinsicck::InlineAsmCtxt;
|
||||
use crate::check::method::MethodCallee;
|
||||
use crate::check::Expectation::*;
|
||||
use crate::check::TupleArgumentsFlag::*;
|
||||
|
@ -59,7 +60,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
debug!("FnCtxt::check_asm: {} deferred checks", deferred_asm_checks.len());
|
||||
for (asm, hir_id) in deferred_asm_checks.drain(..) {
|
||||
let enclosing_id = self.tcx.hir().enclosing_body_owner(hir_id);
|
||||
self.check_asm(asm, enclosing_id);
|
||||
InlineAsmCtxt::new_in_fn(self).check_asm(asm, enclosing_id);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -103,7 +103,7 @@ impl<'tcx> InheritedBuilder<'tcx> {
|
|||
}
|
||||
|
||||
impl<'a, 'tcx> Inherited<'a, 'tcx> {
|
||||
pub(super) fn new(infcx: InferCtxt<'a, 'tcx>, def_id: LocalDefId) -> Self {
|
||||
fn new(infcx: InferCtxt<'a, 'tcx>, def_id: LocalDefId) -> Self {
|
||||
let tcx = infcx.tcx;
|
||||
let item_id = tcx.hir().local_def_id_to_hir_id(def_id);
|
||||
let body_id = tcx.hir().maybe_body_owned_by(item_id);
|
||||
|
@ -113,7 +113,7 @@ impl<'a, 'tcx> Inherited<'a, 'tcx> {
|
|||
maybe_typeck_results: infcx.in_progress_typeck_results,
|
||||
},
|
||||
infcx,
|
||||
fulfillment_cx: RefCell::new(<dyn TraitEngine<'_>>::new(tcx)),
|
||||
fulfillment_cx: RefCell::new(<dyn TraitEngine<'_>>::new_ignoring_regions(tcx)),
|
||||
locals: RefCell::new(Default::default()),
|
||||
deferred_sized_obligations: RefCell::new(Vec::new()),
|
||||
deferred_call_resolutions: RefCell::new(Default::default()),
|
||||
|
|
|
@ -111,6 +111,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub struct InlineAsmCtxt<'a, 'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
fcx: Option<&'a FnCtxt<'a, 'tcx>>,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
|
||||
pub fn new_global_asm(tcx: TyCtxt<'tcx>) -> Self {
|
||||
InlineAsmCtxt { tcx, fcx: None }
|
||||
}
|
||||
|
||||
pub fn new_in_fn(fcx: &'a FnCtxt<'a, 'tcx>) -> Self {
|
||||
InlineAsmCtxt { tcx: fcx.tcx, fcx: Some(fcx) }
|
||||
}
|
||||
|
||||
fn check_asm_operand_type(
|
||||
&self,
|
||||
|
@ -122,9 +137,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
tied_input: Option<(&hir::Expr<'tcx>, Option<InlineAsmType>)>,
|
||||
target_features: &FxHashSet<Symbol>,
|
||||
) -> Option<InlineAsmType> {
|
||||
let fcx = self.fcx.unwrap_or_else(|| span_bug!(expr.span, "asm operand for global asm"));
|
||||
// Check the type against the allowed types for inline asm.
|
||||
let ty = self.typeck_results.borrow().expr_ty_adjusted(expr);
|
||||
let ty = self.resolve_vars_if_possible(ty);
|
||||
let ty = fcx.typeck_results.borrow().expr_ty_adjusted(expr);
|
||||
let ty = fcx.resolve_vars_if_possible(ty);
|
||||
let asm_ty_isize = match self.tcx.sess.target.pointer_width {
|
||||
16 => InlineAsmType::I16,
|
||||
32 => InlineAsmType::I32,
|
||||
|
@ -134,7 +150,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
// Expect types to be fully resolved, no const or type variables.
|
||||
if ty.has_infer_types_or_consts() {
|
||||
assert!(self.is_tainted_by_errors());
|
||||
assert!(fcx.is_tainted_by_errors());
|
||||
return None;
|
||||
}
|
||||
|
||||
|
@ -151,7 +167,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
ty::Float(FloatTy::F32) => Some(InlineAsmType::F32),
|
||||
ty::Float(FloatTy::F64) => Some(InlineAsmType::F64),
|
||||
ty::FnPtr(_) => Some(asm_ty_isize),
|
||||
ty::RawPtr(ty::TypeAndMut { ty, mutbl: _ }) if self.is_thin_ptr_ty(ty) => {
|
||||
ty::RawPtr(ty::TypeAndMut { ty, mutbl: _ }) if fcx.is_thin_ptr_ty(ty) => {
|
||||
Some(asm_ty_isize)
|
||||
}
|
||||
ty::Adt(adt, substs) if adt.repr().simd() => {
|
||||
|
@ -203,7 +219,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
// Check that the type implements Copy. The only case where this can
|
||||
// possibly fail is for SIMD types which don't #[derive(Copy)].
|
||||
if !self.infcx.type_is_copy_modulo_regions(self.param_env, ty, DUMMY_SP) {
|
||||
if !fcx.infcx.type_is_copy_modulo_regions(fcx.param_env, ty, DUMMY_SP) {
|
||||
let msg = "arguments for inline assembly must be copyable";
|
||||
let mut err = self.tcx.sess.struct_span_err(expr.span, msg);
|
||||
err.note(&format!("`{ty}` does not implement the Copy trait"));
|
||||
|
@ -224,8 +240,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let msg = "incompatible types for asm inout argument";
|
||||
let mut err = self.tcx.sess.struct_span_err(vec![in_expr.span, expr.span], msg);
|
||||
|
||||
let in_expr_ty = self.typeck_results.borrow().expr_ty_adjusted(in_expr);
|
||||
let in_expr_ty = self.resolve_vars_if_possible(in_expr_ty);
|
||||
let in_expr_ty = fcx.typeck_results.borrow().expr_ty_adjusted(in_expr);
|
||||
let in_expr_ty = fcx.resolve_vars_if_possible(in_expr_ty);
|
||||
err.span_label(in_expr.span, &format!("type `{in_expr_ty}`"));
|
||||
err.span_label(expr.span, &format!("type `{ty}`"));
|
||||
err.note(
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -349,7 +349,7 @@ fn visit_implementation_of_dispatch_from_dyn<'tcx>(tcx: TyCtxt<'tcx>, impl_did:
|
|||
|
||||
// Finally, resolve all regions.
|
||||
let outlives_env = OutlivesEnvironment::new(param_env);
|
||||
infcx.resolve_regions_and_report_errors(&outlives_env);
|
||||
infcx.resolve_regions_and_report_errors(impl_did, &outlives_env);
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
|
@ -606,7 +606,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn
|
|||
|
||||
// Finally, resolve all regions.
|
||||
let outlives_env = OutlivesEnvironment::new(param_env);
|
||||
infcx.resolve_regions_and_report_errors(&outlives_env);
|
||||
infcx.resolve_regions_and_report_errors(impl_did, &outlives_env);
|
||||
|
||||
CoerceUnsizedInfo { custom_kind: kind }
|
||||
})
|
||||
|
|
|
@ -150,7 +150,7 @@ fn get_impl_substs<'tcx>(
|
|||
|
||||
// Conservatively use an empty `ParamEnv`.
|
||||
let outlives_env = OutlivesEnvironment::new(ty::ParamEnv::empty());
|
||||
infcx.resolve_regions_and_report_errors(&outlives_env);
|
||||
infcx.resolve_regions_and_report_errors(impl1_def_id, &outlives_env);
|
||||
let Ok(impl2_substs) = infcx.fully_resolve(impl2_substs) else {
|
||||
let span = tcx.def_span(impl1_def_id);
|
||||
tcx.sess.emit_err(SubstsOnOverriddenImpl { span });
|
||||
|
|
|
@ -2,10 +2,12 @@ error[E0310]: the parameter type `T` may not live long enough
|
|||
--> $DIR/implied-bounds-unnorm-associated-type-3.rs:19:5
|
||||
|
|
||||
LL | fn zero_copy_from<'b>(cart: &'b [T]) -> &'b [T] {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `[T]` will meet its required lifetime bounds
|
||||
|
|
||||
= help: consider adding an explicit lifetime bound `T: 'static`...
|
||||
= note: ...so that the type `[T]` will meet its required lifetime bounds
|
||||
help: consider adding an explicit lifetime bound...
|
||||
|
|
||||
LL | impl<T: 'static> ZeroCopyFrom<[T]> for &'static [T] {
|
||||
| +++++++++
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -23,7 +23,6 @@ where
|
|||
// Here we get an error: we need `'a: 'b`.
|
||||
fn bar<'a, 'b>()
|
||||
//~^ ERROR cannot infer
|
||||
//~| ERROR cannot infer
|
||||
where
|
||||
<() as Project<'a, 'b>>::Item: Eq,
|
||||
{
|
||||
|
|
|
@ -1,35 +1,3 @@
|
|||
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
|
||||
--> $DIR/regions-normalize-in-where-clause-list.rs:24:1
|
||||
|
|
||||
LL | / fn bar<'a, 'b>()
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | where
|
||||
LL | | <() as Project<'a, 'b>>::Item: Eq,
|
||||
| |______________________________________^
|
||||
|
|
||||
note: first, the lifetime cannot outlive the lifetime `'a` as defined here...
|
||||
--> $DIR/regions-normalize-in-where-clause-list.rs:24:8
|
||||
|
|
||||
LL | fn bar<'a, 'b>()
|
||||
| ^^
|
||||
note: ...but the lifetime must also be valid for the lifetime `'b` as defined here...
|
||||
--> $DIR/regions-normalize-in-where-clause-list.rs:24:12
|
||||
|
|
||||
LL | fn bar<'a, 'b>()
|
||||
| ^^
|
||||
note: ...so that the types are compatible
|
||||
--> $DIR/regions-normalize-in-where-clause-list.rs:24:1
|
||||
|
|
||||
LL | / fn bar<'a, 'b>()
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | where
|
||||
LL | | <() as Project<'a, 'b>>::Item: Eq,
|
||||
| |______________________________________^
|
||||
= note: expected `Project<'a, 'b>`
|
||||
found `Project<'_, '_>`
|
||||
|
||||
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
|
||||
--> $DIR/regions-normalize-in-where-clause-list.rs:24:4
|
||||
|
|
||||
|
@ -54,6 +22,6 @@ LL | fn bar<'a, 'b>()
|
|||
= note: expected `Project<'a, 'b>`
|
||||
found `Project<'_, '_>`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0495`.
|
||||
|
|
|
@ -11,12 +11,10 @@ LL | impl<B: ?Sized + std::clone::Clone> Display for Cow<'_, B> {
|
|||
| +++++++++++++++++++
|
||||
|
||||
error[E0277]: the trait bound `B: Clone` is not satisfied
|
||||
--> $DIR/issue-79224.rs:19:5
|
||||
--> $DIR/issue-79224.rs:19:12
|
||||
|
|
||||
LL | / fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
LL | | write!(f, "foo")
|
||||
LL | | }
|
||||
| |_____^ the trait `Clone` is not implemented for `B`
|
||||
LL | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
| ^^^^^ the trait `Clone` is not implemented for `B`
|
||||
|
|
||||
= note: required because of the requirements on the impl of `ToOwned` for `B`
|
||||
help: consider further restricting this bound
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue