summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_hir_analysis/src/coherence
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_hir_analysis/src/coherence')
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/builtin.rs72
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs12
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/mod.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/orphan.rs4
5 files changed, 48 insertions, 46 deletions
diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
index ffb68abf9..0f40cca94 100644
--- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
@@ -2,21 +2,23 @@
//! up data structures required by type-checking/codegen.
use crate::errors::{CopyImplOnNonAdt, CopyImplOnTypeWithDtor, DropImplOnWrongItem};
+use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{struct_span_err, MultiSpan};
use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::lang_items::LangItem;
use rustc_hir::ItemKind;
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
-use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::infer::{self, RegionResolutionError};
+use rustc_infer::infer::{DefineOpaqueTypes, TyCtxtInferExt};
+use rustc_infer::traits::Obligation;
use rustc_middle::ty::adjustment::CoerceUnsizedInfo;
use rustc_middle::ty::{self, suggest_constraining_type_params, Ty, TyCtxt, TypeVisitableExt};
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
use rustc_trait_selection::traits::misc::{
type_allowed_to_implement_copy, CopyImplementationError, InfringingFieldsReason,
};
-use rustc_trait_selection::traits::predicate_for_trait_def;
+use rustc_trait_selection::traits::ObligationCtxt;
use rustc_trait_selection::traits::{self, ObligationCause};
use std::collections::BTreeMap;
@@ -86,7 +88,7 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
tcx.sess,
span,
E0204,
- "the trait `Copy` may not be implemented for this type"
+ "the trait `Copy` cannot be implemented for this type"
);
// We'll try to suggest constraining type parameters to fulfill the requirements of
@@ -94,7 +96,14 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
let mut errors: BTreeMap<_, Vec<_>> = Default::default();
let mut bounds = vec![];
+ let mut seen_tys = FxHashSet::default();
+
for (field, ty, reason) in fields {
+ // Only report an error once per type.
+ if !seen_tys.insert(ty) {
+ continue;
+ }
+
let field_span = tcx.def_span(field.did);
err.span_label(field_span, "this field does not implement `Copy`");
@@ -227,7 +236,8 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
use rustc_type_ir::sty::TyKind::*;
match (source.kind(), target.kind()) {
(&Ref(r_a, _, mutbl_a), Ref(r_b, _, mutbl_b))
- if infcx.at(&cause, param_env).eq(r_a, *r_b).is_ok() && mutbl_a == *mutbl_b => {}
+ if infcx.at(&cause, param_env).eq(DefineOpaqueTypes::No, r_a, *r_b).is_ok()
+ && mutbl_a == *mutbl_b => {}
(&RawPtr(tm_a), &RawPtr(tm_b)) if tm_a.mutbl == tm_b.mutbl => (),
(&Adt(def_a, substs_a), &Adt(def_b, substs_b))
if def_a.is_struct() && def_b.is_struct() =>
@@ -270,7 +280,9 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
}
}
- if let Ok(ok) = infcx.at(&cause, param_env).eq(ty_a, ty_b) {
+ if let Ok(ok) =
+ infcx.at(&cause, param_env).eq(DefineOpaqueTypes::No, ty_a, ty_b)
+ {
if ok.obligations.is_empty() {
create_err(
"the trait `DispatchFromDyn` may only be implemented \
@@ -323,28 +335,26 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
))
.emit();
} else {
- let errors = traits::fully_solve_obligations(
- &infcx,
- coerced_fields.into_iter().map(|field| {
- predicate_for_trait_def(
- tcx,
- param_env,
- cause.clone(),
+ let ocx = ObligationCtxt::new(&infcx);
+ for field in coerced_fields {
+ ocx.register_obligation(Obligation::new(
+ tcx,
+ cause.clone(),
+ param_env,
+ ty::Binder::dummy(tcx.mk_trait_ref(
dispatch_from_dyn_trait,
- 0,
[field.ty(tcx, substs_a), field.ty(tcx, substs_b)],
- )
- }),
- );
+ )),
+ ));
+ }
+ let errors = ocx.select_all_or_error();
if !errors.is_empty() {
- infcx.err_ctxt().report_fulfillment_errors(&errors, None);
+ infcx.err_ctxt().report_fulfillment_errors(&errors);
}
// Finally, resolve all regions.
let outlives_env = OutlivesEnvironment::new(param_env);
- let _ = infcx
- .err_ctxt()
- .check_region_obligations_and_report_errors(impl_did, &outlives_env);
+ let _ = ocx.resolve_regions_and_report_errors(impl_did, &outlives_env);
}
}
_ => {
@@ -357,11 +367,8 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
}
}
-pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUnsizedInfo {
+pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> CoerceUnsizedInfo {
debug!("compute_coerce_unsized_info(impl_did={:?})", impl_did);
-
- // this provider should only get invoked for local def-ids
- let impl_did = impl_did.expect_local();
let span = tcx.def_span(impl_did);
let coerce_unsized_trait = tcx.require_lang_item(LangItem::CoerceUnsized, Some(span));
@@ -477,8 +484,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn
// U` can be coerced to `*mut V` if `U: Unsize<V>`.
let fields = &def_a.non_enum_variant().fields;
let diff_fields = fields
- .iter()
- .enumerate()
+ .iter_enumerated()
.filter_map(|(i, f)| {
let (a, b) = (f.ty(tcx, substs_a), f.ty(tcx, substs_b));
@@ -496,7 +502,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn
// we may have to evaluate constraint
// expressions in the course of execution.)
// See e.g., #41936.
- if let Ok(ok) = infcx.at(&cause, param_env).eq(a, b) {
+ if let Ok(ok) = infcx.at(&cause, param_env).eq(DefineOpaqueTypes::No, a, b) {
if ok.obligations.is_empty() {
return None;
}
@@ -572,17 +578,19 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn
};
// Register an obligation for `A: Trait<B>`.
+ let ocx = ObligationCtxt::new(&infcx);
let cause = traits::ObligationCause::misc(span, impl_did);
- let predicate =
- predicate_for_trait_def(tcx, param_env, cause, trait_def_id, 0, [source, target]);
- let errors = traits::fully_solve_obligation(&infcx, predicate);
+ let obligation =
+ Obligation::new(tcx, cause, param_env, tcx.mk_trait_ref(trait_def_id, [source, target]));
+ ocx.register_obligation(obligation);
+ let errors = ocx.select_all_or_error();
if !errors.is_empty() {
- infcx.err_ctxt().report_fulfillment_errors(&errors, None);
+ infcx.err_ctxt().report_fulfillment_errors(&errors);
}
// Finally, resolve all regions.
let outlives_env = OutlivesEnvironment::new(param_env);
- let _ = infcx.err_ctxt().check_region_obligations_and_report_errors(impl_did, &outlives_env);
+ let _ = ocx.resolve_regions_and_report_errors(impl_did, &outlives_env);
CoerceUnsizedInfo { custom_kind: kind }
}
diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
index 02f3eeee0..3d37e0ce0 100644
--- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
@@ -10,7 +10,7 @@
use rustc_errors::struct_span_err;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
-use rustc_hir::def_id::{CrateNum, DefId, LocalDefId};
+use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_middle::ty::fast_reject::{simplify_type, SimplifiedType, TreatParams};
use rustc_middle::ty::{self, CrateInherentImpls, Ty, TyCtxt};
use rustc_span::symbol::sym;
@@ -24,7 +24,7 @@ pub fn crate_inherent_impls(tcx: TyCtxt<'_>, (): ()) -> CrateInherentImpls {
collect.impls_map
}
-pub fn crate_incoherent_impls(tcx: TyCtxt<'_>, (_, simp): (CrateNum, SimplifiedType)) -> &[DefId] {
+pub fn crate_incoherent_impls(tcx: TyCtxt<'_>, simp: SimplifiedType) -> &[DefId] {
let crate_map = tcx.crate_inherent_impls(());
tcx.arena.alloc_from_iter(
crate_map.incoherent_impls.get(&simp).unwrap_or(&Vec::new()).iter().map(|d| d.to_def_id()),
@@ -32,9 +32,7 @@ pub fn crate_incoherent_impls(tcx: TyCtxt<'_>, (_, simp): (CrateNum, SimplifiedT
}
/// On-demand query: yields a vector of the inherent impls for a specific type.
-pub fn inherent_impls(tcx: TyCtxt<'_>, ty_def_id: DefId) -> &[DefId] {
- let ty_def_id = ty_def_id.expect_local();
-
+pub fn inherent_impls(tcx: TyCtxt<'_>, ty_def_id: LocalDefId) -> &[DefId] {
let crate_map = tcx.crate_inherent_impls(());
match crate_map.inherent_impls.get(&ty_def_id) {
Some(v) => &v[..],
@@ -99,7 +97,7 @@ impl<'tcx> InherentCollect<'tcx> {
}
}
- if let Some(simp) = simplify_type(self.tcx, self_ty, TreatParams::AsInfer) {
+ if let Some(simp) = simplify_type(self.tcx, self_ty, TreatParams::AsCandidateKey) {
self.impls_map.incoherent_impls.entry(simp).or_default().push(impl_def_id);
} else {
bug!("unexpected self type: {:?}", self_ty);
@@ -159,7 +157,7 @@ impl<'tcx> InherentCollect<'tcx> {
}
}
- if let Some(simp) = simplify_type(self.tcx, ty, TreatParams::AsInfer) {
+ if let Some(simp) = simplify_type(self.tcx, ty, TreatParams::AsCandidateKey) {
self.impls_map.incoherent_impls.entry(simp).or_default().push(impl_def_id);
} else {
bug!("unexpected primitive type: {:?}", ty);
diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs
index 7bca4edcc..ad76e2bed 100644
--- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs
@@ -302,7 +302,7 @@ impl<'tcx> InherentOverlapChecker<'tcx> {
.iter()
.flatten()
.map(|r| r.impl_blocks.len() as isize - avg as isize)
- .map(|v| v.abs() as usize)
+ .map(|v| v.unsigned_abs())
.sum::<usize>();
s / connected_regions.len()
},
diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs
index 23490bc09..465e787c9 100644
--- a/compiler/rustc_hir_analysis/src/coherence/mod.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs
@@ -133,8 +133,8 @@ fn coherent_trait(tcx: TyCtxt<'_>, def_id: DefId) {
check_impl(tcx, impl_def_id, trait_ref);
check_object_overlap(tcx, impl_def_id, trait_ref);
- tcx.sess.time("unsafety_checking", || unsafety::check_item(tcx, impl_def_id));
- tcx.sess.time("orphan_checking", || tcx.ensure().orphan_check_impl(impl_def_id));
+ unsafety::check_item(tcx, impl_def_id);
+ tcx.ensure().orphan_check_impl(impl_def_id);
}
builtin::check_trait(tcx, def_id);
diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
index 1f2de3f21..47c47de8c 100644
--- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
@@ -478,10 +478,6 @@ fn lint_auto_trait_impl<'tcx>(
trait_ref: ty::TraitRef<'tcx>,
impl_def_id: LocalDefId,
) {
- if tcx.impl_polarity(impl_def_id) != ImplPolarity::Positive {
- return;
- }
-
assert_eq!(trait_ref.substs.len(), 1);
let self_ty = trait_ref.self_ty();
let (self_type_did, substs) = match self_ty.kind() {