-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
//! Check properties that are required by built-in traits and set
-//! up data structures required by type-checking/translation.
-
-use rustc::middle::free_region::FreeRegionMap;
-use rustc::middle::region::RegionMaps;
-use rustc::middle::lang_items::UnsizeTraitLangItem;
-
-use rustc::traits::{self, ObligationCause};
-use rustc::ty::{self, Ty, TyCtxt};
-use rustc::ty::TypeFoldable;
-use rustc::ty::adjustment::CoerceUnsizedInfo;
-use rustc::ty::util::CopyImplementationError;
-use rustc::infer;
-
-use rustc::hir::def_id::DefId;
-use rustc::hir::map as hir_map;
-use rustc::hir::{self, ItemImpl};
-
-pub fn check_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_def_id: DefId) {
+//! up data structures required by type-checking/codegen.
+
+use rustc_errors::struct_span_err;
+use rustc_hir as hir;
+use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::lang_items::{
+ CoerceUnsizedTraitLangItem, DispatchFromDynTraitLangItem, UnsizeTraitLangItem,
+};
+use rustc_hir::ItemKind;
+use rustc_infer::infer;
+use rustc_infer::infer::outlives::env::OutlivesEnvironment;
+use rustc_infer::infer::{RegionckMode, TyCtxtInferExt};
+use rustc_middle::ty::adjustment::CoerceUnsizedInfo;
+use rustc_middle::ty::TypeFoldable;
+use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
+use rustc_trait_selection::traits::misc::{can_type_implement_copy, CopyImplementationError};
+use rustc_trait_selection::traits::predicate_for_trait_def;
+use rustc_trait_selection::traits::{self, ObligationCause, TraitEngine, TraitEngineExt};
+
+pub fn check_trait(tcx: TyCtxt<'_>, trait_def_id: DefId) {
+ let lang_items = tcx.lang_items();
Checker { tcx, trait_def_id }
- .check(tcx.lang_items.drop_trait(), visit_implementation_of_drop)
- .check(tcx.lang_items.copy_trait(), visit_implementation_of_copy)
- .check(tcx.lang_items.coerce_unsized_trait(),
- visit_implementation_of_coerce_unsized);
+ .check(lang_items.drop_trait(), visit_implementation_of_drop)
+ .check(lang_items.copy_trait(), visit_implementation_of_copy)
+ .check(lang_items.coerce_unsized_trait(), visit_implementation_of_coerce_unsized)
+ .check(lang_items.dispatch_from_dyn_trait(), visit_implementation_of_dispatch_from_dyn);
}
-struct Checker<'a, 'tcx: 'a> {
- tcx: TyCtxt<'a, 'tcx, 'tcx>,
- trait_def_id: DefId
+struct Checker<'tcx> {
+ tcx: TyCtxt<'tcx>,
+ trait_def_id: DefId,
}
-impl<'a, 'tcx> Checker<'a, 'tcx> {
+impl<'tcx> Checker<'tcx> {
fn check<F>(&self, trait_def_id: Option<DefId>, mut f: F) -> &Self
- where F: FnMut(TyCtxt<'a, 'tcx, 'tcx>, DefId, DefId)
+ where
+ F: FnMut(TyCtxt<'tcx>, LocalDefId),
{
if Some(self.trait_def_id) == trait_def_id {
- for &impl_id in self.tcx.hir.trait_impls(self.trait_def_id) {
- let impl_def_id = self.tcx.hir.local_def_id(impl_id);
- f(self.tcx, self.trait_def_id, impl_def_id);
+ for &impl_id in self.tcx.hir().trait_impls(self.trait_def_id) {
+ let impl_def_id = self.tcx.hir().local_def_id(impl_id);
+ f(self.tcx, impl_def_id);
}
}
self
}
}
-fn visit_implementation_of_drop<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
- _drop_did: DefId,
- impl_did: DefId) {
- match tcx.type_of(impl_did).sty {
- ty::TyAdt(..) => {}
- _ => {
- // Destructors only work on nominal types.
- if let Some(impl_node_id) = tcx.hir.as_local_node_id(impl_did) {
- match tcx.hir.find(impl_node_id) {
- Some(hir_map::NodeItem(item)) => {
- let span = match item.node {
- ItemImpl(.., ref ty, _) => ty.span,
- _ => item.span,
- };
- struct_span_err!(tcx.sess,
- span,
- E0120,
- "the Drop trait may only be implemented on \
- structures")
- .span_label(span, "implementing Drop requires a struct")
- .emit();
- }
- _ => {
- bug!("didn't find impl in ast map");
- }
- }
- } else {
- bug!("found external impl of Drop trait on \
- something other than a struct");
- }
- }
+fn visit_implementation_of_drop(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
+ // Destructors only work on nominal types.
+ if let ty::Adt(..) | ty::Error(_) = tcx.type_of(impl_did).kind {
+ return;
}
+
+ let impl_hir_id = tcx.hir().as_local_hir_id(impl_did);
+ let sp = match tcx.hir().expect_item(impl_hir_id).kind {
+ ItemKind::Impl { self_ty, .. } => self_ty.span,
+ _ => bug!("expected Drop impl item"),
+ };
+
+ struct_span_err!(
+ tcx.sess,
+ sp,
+ E0120,
+ "the `Drop` trait may only be implemented for structs, enums, and unions",
+ )
+ .span_label(sp, "must be a struct, enum, or union")
+ .emit();
}
-fn visit_implementation_of_copy<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
- _copy_did: DefId,
- impl_did: DefId) {
+fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
debug!("visit_implementation_of_copy: impl_did={:?}", impl_did);
- let impl_node_id = if let Some(n) = tcx.hir.as_local_node_id(impl_did) {
- n
- } else {
- debug!("visit_implementation_of_copy(): impl not in this \
- crate");
- return;
- };
+ let impl_hir_id = tcx.hir().as_local_hir_id(impl_did);
let self_type = tcx.type_of(impl_did);
- debug!("visit_implementation_of_copy: self_type={:?} (bound)",
- self_type);
+ debug!("visit_implementation_of_copy: self_type={:?} (bound)", self_type);
- let span = tcx.hir.span(impl_node_id);
+ let span = tcx.hir().span(impl_hir_id);
let param_env = tcx.param_env(impl_did);
- assert!(!self_type.has_escaping_regions());
+ assert!(!self_type.has_escaping_bound_vars());
- debug!("visit_implementation_of_copy: self_type={:?} (free)",
- self_type);
+ debug!("visit_implementation_of_copy: self_type={:?} (free)", self_type);
- match param_env.can_type_implement_copy(tcx, self_type, span) {
+ match can_type_implement_copy(tcx, param_env, self_type) {
Ok(()) => {}
- Err(CopyImplementationError::InfrigingField(field)) => {
- let item = tcx.hir.expect_item(impl_node_id);
- let span = if let ItemImpl(.., Some(ref tr), _, _) = item.node {
+ Err(CopyImplementationError::InfrigingFields(fields)) => {
+ let item = tcx.hir().expect_item(impl_hir_id);
+ let span = if let ItemKind::Impl { of_trait: Some(ref tr), .. } = item.kind {
tr.path.span
} else {
span
};
- struct_span_err!(tcx.sess,
- span,
- E0204,
- "the trait `Copy` may not be implemented for this type")
- .span_label(
- tcx.def_span(field.did),
- "this field does not implement `Copy`")
- .emit()
+ let mut err = struct_span_err!(
+ tcx.sess,
+ span,
+ E0204,
+ "the trait `Copy` may not be implemented for this type"
+ );
+ for span in fields.iter().map(|f| tcx.def_span(f.did)) {
+ err.span_label(span, "this field does not implement `Copy`");
+ }
+ err.emit()
}
Err(CopyImplementationError::NotAnAdt) => {
- let item = tcx.hir.expect_item(impl_node_id);
- let span = if let ItemImpl(.., ref ty, _) = item.node {
- ty.span
- } else {
- span
- };
-
- struct_span_err!(tcx.sess,
- span,
- E0206,
- "the trait `Copy` may not be implemented for this type")
- .span_label(span, "type is not a structure or enumeration")
- .emit();
+ let item = tcx.hir().expect_item(impl_hir_id);
+ let span =
+ if let ItemKind::Impl { self_ty, .. } = item.kind { self_ty.span } else { span };
+
+ struct_span_err!(
+ tcx.sess,
+ span,
+ E0206,
+ "the trait `Copy` may not be implemented for this type"
+ )
+ .span_label(span, "type is not a structure or enumeration")
+ .emit();
}
Err(CopyImplementationError::HasDestructor) => {
- struct_span_err!(tcx.sess,
- span,
- E0184,
- "the trait `Copy` may not be implemented for this type; the \
- type has a destructor")
- .span_label(span, "Copy not allowed on types with destructors")
- .emit();
+ struct_span_err!(
+ tcx.sess,
+ span,
+ E0184,
+ "the trait `Copy` may not be implemented for this type; the \
+ type has a destructor"
+ )
+ .span_label(span, "Copy not allowed on types with destructors")
+ .emit();
}
}
}
-fn visit_implementation_of_coerce_unsized<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
- _: DefId,
- impl_did: DefId) {
- debug!("visit_implementation_of_coerce_unsized: impl_did={:?}",
- impl_did);
+fn visit_implementation_of_coerce_unsized(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) {
+ debug!("visit_implementation_of_coerce_unsized: impl_did={:?}", impl_did);
// Just compute this for the side-effects, in particular reporting
// errors; other parts of the code may demand it for the info of
// course.
- if impl_did.is_local() {
- let span = tcx.def_span(impl_did);
- tcx.at(span).coerce_unsized_info(impl_did);
- }
+ let span = tcx.def_span(impl_did);
+ tcx.at(span).coerce_unsized_info(impl_did);
}
-pub fn coerce_unsized_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
- impl_did: DefId)
- -> CoerceUnsizedInfo {
- debug!("compute_coerce_unsized_info(impl_did={:?})", impl_did);
- let coerce_unsized_trait = tcx.lang_items.coerce_unsized_trait().unwrap();
+fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
+ debug!("visit_implementation_of_dispatch_from_dyn: impl_did={:?}", impl_did);
- let unsize_trait = match tcx.lang_items.require(UnsizeTraitLangItem) {
- Ok(id) => id,
- Err(err) => {
- tcx.sess.fatal(&format!("`CoerceUnsized` implementation {}", err));
- }
+ let impl_hir_id = tcx.hir().as_local_hir_id(impl_did);
+ let span = tcx.hir().span(impl_hir_id);
+
+ let dispatch_from_dyn_trait = tcx.require_lang_item(DispatchFromDynTraitLangItem, Some(span));
+
+ let source = tcx.type_of(impl_did);
+ assert!(!source.has_escaping_bound_vars());
+ let target = {
+ let trait_ref = tcx.impl_trait_ref(impl_did).unwrap();
+ assert_eq!(trait_ref.def_id, dispatch_from_dyn_trait);
+
+ trait_ref.substs.type_at(1)
};
+ debug!("visit_implementation_of_dispatch_from_dyn: {:?} -> {:?}", source, target);
+
+ let param_env = tcx.param_env(impl_did);
+
+ let create_err = |msg: &str| struct_span_err!(tcx.sess, span, E0378, "{}", msg);
+
+ tcx.infer_ctxt().enter(|infcx| {
+ let cause = ObligationCause::misc(span, impl_hir_id);
+
+ use ty::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 => {}
+ (&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() =>
+ {
+ if def_a != def_b {
+ let source_path = tcx.def_path_str(def_a.did);
+ let target_path = tcx.def_path_str(def_b.did);
+
+ create_err(&format!(
+ "the trait `DispatchFromDyn` may only be implemented \
+ for a coercion between structures with the same \
+ definition; expected `{}`, found `{}`",
+ source_path, target_path,
+ ))
+ .emit();
+
+ return;
+ }
+
+ if def_a.repr.c() || def_a.repr.packed() {
+ create_err(
+ "structs implementing `DispatchFromDyn` may not have \
+ `#[repr(packed)]` or `#[repr(C)]`",
+ )
+ .emit();
+ }
+
+ let fields = &def_a.non_enum_variant().fields;
+
+ let coerced_fields = fields
+ .iter()
+ .filter_map(|field| {
+ let ty_a = field.ty(tcx, substs_a);
+ let ty_b = field.ty(tcx, substs_b);
+
+ if let Ok(layout) = tcx.layout_of(param_env.and(ty_a)) {
+ if layout.is_zst() && layout.align.abi.bytes() == 1 {
+ // ignore ZST fields with alignment of 1 byte
+ return None;
+ }
+ }
+
+ if let Ok(ok) = infcx.at(&cause, param_env).eq(ty_a, ty_b) {
+ if ok.obligations.is_empty() {
+ create_err(
+ "the trait `DispatchFromDyn` may only be implemented \
+ for structs containing the field being coerced, \
+ ZST fields with 1 byte alignment, and nothing else",
+ )
+ .note(&format!(
+ "extra field `{}` of type `{}` is not allowed",
+ field.ident, ty_a,
+ ))
+ .emit();
+
+ return None;
+ }
+ }
+
+ Some(field)
+ })
+ .collect::<Vec<_>>();
+
+ if coerced_fields.is_empty() {
+ create_err(
+ "the trait `DispatchFromDyn` may only be implemented \
+ for a coercion between structures with a single field \
+ being coerced, none found",
+ )
+ .emit();
+ } else if coerced_fields.len() > 1 {
+ create_err(
+ "implementing the `DispatchFromDyn` trait requires multiple coercions",
+ )
+ .note(
+ "the trait `DispatchFromDyn` may only be implemented \
+ for a coercion between structures with a single field \
+ being coerced",
+ )
+ .note(&format!(
+ "currently, {} fields need coercions: {}",
+ coerced_fields.len(),
+ coerced_fields
+ .iter()
+ .map(|field| {
+ format!(
+ "`{}` (`{}` to `{}`)",
+ field.ident,
+ field.ty(tcx, substs_a),
+ field.ty(tcx, substs_b),
+ )
+ })
+ .collect::<Vec<_>>()
+ .join(", ")
+ ))
+ .emit();
+ } else {
+ let mut fulfill_cx = TraitEngine::new(infcx.tcx);
+
+ for field in coerced_fields {
+ let predicate = predicate_for_trait_def(
+ tcx,
+ param_env,
+ cause.clone(),
+ dispatch_from_dyn_trait,
+ 0,
+ field.ty(tcx, substs_a),
+ &[field.ty(tcx, substs_b).into()],
+ );
+
+ fulfill_cx.register_predicate_obligation(&infcx, predicate);
+ }
+
+ // Check that all transitive obligations are satisfied.
+ if let Err(errors) = fulfill_cx.select_all_or_error(&infcx) {
+ infcx.report_fulfillment_errors(&errors, None, false);
+ }
+
+ // Finally, resolve all regions.
+ let outlives_env = OutlivesEnvironment::new(param_env);
+ infcx.resolve_regions_and_report_errors(
+ impl_did.to_def_id(),
+ &outlives_env,
+ RegionckMode::default(),
+ );
+ }
+ }
+ _ => {
+ create_err(
+ "the trait `DispatchFromDyn` may only be implemented \
+ for a coercion between structures",
+ )
+ .emit();
+ }
+ }
+ })
+}
+
+pub fn coerce_unsized_info(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUnsizedInfo {
+ debug!("compute_coerce_unsized_info(impl_did={:?})", impl_did);
+
// this provider should only get invoked for local def-ids
- let impl_node_id = tcx.hir.as_local_node_id(impl_did).unwrap_or_else(|| {
- bug!("coerce_unsized_info: invoked for non-local def-id {:?}", impl_did)
+ let impl_hir_id = tcx.hir().as_local_hir_id(impl_did.expect_local());
+ let span = tcx.hir().span(impl_hir_id);
+
+ let coerce_unsized_trait = tcx.require_lang_item(CoerceUnsizedTraitLangItem, Some(span));
+
+ let unsize_trait = tcx.lang_items().require(UnsizeTraitLangItem).unwrap_or_else(|err| {
+ tcx.sess.fatal(&format!("`CoerceUnsized` implementation {}", err));
});
let source = tcx.type_of(impl_did);
let trait_ref = tcx.impl_trait_ref(impl_did).unwrap();
assert_eq!(trait_ref.def_id, coerce_unsized_trait);
let target = trait_ref.substs.type_at(1);
- debug!("visit_implementation_of_coerce_unsized: {:?} -> {:?} (bound)",
- source,
- target);
+ debug!("visit_implementation_of_coerce_unsized: {:?} -> {:?} (bound)", source, target);
- let span = tcx.hir.span(impl_node_id);
let param_env = tcx.param_env(impl_did);
- assert!(!source.has_escaping_regions());
+ assert!(!source.has_escaping_bound_vars());
let err_info = CoerceUnsizedInfo { custom_kind: None };
- debug!("visit_implementation_of_coerce_unsized: {:?} -> {:?} (free)",
- source,
- target);
+ debug!("visit_implementation_of_coerce_unsized: {:?} -> {:?} (free)", source, target);
tcx.infer_ctxt().enter(|infcx| {
- let cause = ObligationCause::misc(span, impl_node_id);
+ let cause = ObligationCause::misc(span, impl_hir_id);
let check_mutbl = |mt_a: ty::TypeAndMut<'tcx>,
mt_b: ty::TypeAndMut<'tcx>,
- mk_ptr: &Fn(Ty<'tcx>) -> Ty<'tcx>| {
- if (mt_a.mutbl, mt_b.mutbl) == (hir::MutImmutable, hir::MutMutable) {
- infcx.report_mismatched_types(&cause,
- mk_ptr(mt_b.ty),
- target,
- ty::error::TypeError::Mutability)
+ mk_ptr: &dyn Fn(Ty<'tcx>) -> Ty<'tcx>| {
+ if (mt_a.mutbl, mt_b.mutbl) == (hir::Mutability::Not, hir::Mutability::Mut) {
+ infcx
+ .report_mismatched_types(
+ &cause,
+ mk_ptr(mt_b.ty),
+ target,
+ ty::error::TypeError::Mutability,
+ )
.emit();
}
(mt_a.ty, mt_b.ty, unsize_trait, None)
};
- let (source, target, trait_def_id, kind) = match (&source.sty, &target.sty) {
- (&ty::TyRef(r_a, mt_a), &ty::TyRef(r_b, mt_b)) => {
+ let (source, target, trait_def_id, kind) = match (&source.kind, &target.kind) {
+ (&ty::Ref(r_a, ty_a, mutbl_a), &ty::Ref(r_b, ty_b, mutbl_b)) => {
infcx.sub_regions(infer::RelateObjectBound(span), r_b, r_a);
+ let mt_a = ty::TypeAndMut { ty: ty_a, mutbl: mutbl_a };
+ let mt_b = ty::TypeAndMut { ty: ty_b, mutbl: mutbl_b };
check_mutbl(mt_a, mt_b, &|ty| tcx.mk_imm_ref(r_b, ty))
}
- (&ty::TyRef(_, mt_a), &ty::TyRawPtr(mt_b)) |
- (&ty::TyRawPtr(mt_a), &ty::TyRawPtr(mt_b)) => {
+ (&ty::Ref(_, ty_a, mutbl_a), &ty::RawPtr(mt_b)) => {
+ let mt_a = ty::TypeAndMut { ty: ty_a, mutbl: mutbl_a };
+ check_mutbl(mt_a, mt_b, &|ty| tcx.mk_imm_ptr(ty))
+ }
+
+ (&ty::RawPtr(mt_a), &ty::RawPtr(mt_b)) => {
check_mutbl(mt_a, mt_b, &|ty| tcx.mk_imm_ptr(ty))
}
- (&ty::TyAdt(def_a, substs_a), &ty::TyAdt(def_b, substs_b)) if def_a.is_struct() &&
- def_b.is_struct() => {
+ (&ty::Adt(def_a, substs_a), &ty::Adt(def_b, substs_b))
+ if def_a.is_struct() && def_b.is_struct() =>
+ {
if def_a != def_b {
- let source_path = tcx.item_path_str(def_a.did);
- let target_path = tcx.item_path_str(def_b.did);
- span_err!(tcx.sess,
- span,
- E0377,
- "the trait `CoerceUnsized` may only be implemented \
+ let source_path = tcx.def_path_str(def_a.did);
+ let target_path = tcx.def_path_str(def_b.did);
+ struct_span_err!(
+ tcx.sess,
+ span,
+ E0377,
+ "the trait `CoerceUnsized` may only be implemented \
for a coercion between structures with the same \
- definition; expected {}, found {}",
- source_path,
- target_path);
+ definition; expected `{}`, found `{}`",
+ source_path,
+ target_path
+ )
+ .emit();
return err_info;
}
// exactly one (non-phantom) field has changed its
// type, which we will expect to be the pointer that
// is becoming fat (we could probably generalize this
- // to mutiple thin pointers of the same type becoming
+ // to multiple thin pointers of the same type becoming
// fat, but we don't). In this case:
//
// - `extra` has type `T` before and type `T` after
// conversion). This will work out because `U:
// Unsize<V>`, and we have a builtin rule that `*mut
// U` can be coerced to `*mut V` if `U: Unsize<V>`.
- let fields = &def_a.struct_variant().fields;
- let diff_fields = fields.iter()
+ let fields = &def_a.non_enum_variant().fields;
+ let diff_fields = fields
+ .iter()
.enumerate()
.filter_map(|(i, f)| {
let (a, b) = (f.ty(tcx, substs_a), f.ty(tcx, substs_b));
// variance where possible. (This is because
// we may have to evaluate constraint
// expressions in the course of execution.)
- // See e.g. #41936.
+ // See e.g., #41936.
if let Ok(ok) = infcx.at(&cause, param_env).eq(a, b) {
if ok.obligations.is_empty() {
return None;
}
// Collect up all fields that were significantly changed
- // i.e. those that contain T in coerce_unsized T -> U
+ // i.e., those that contain T in coerce_unsized T -> U
Some((i, a, b))
})
.collect::<Vec<_>>();
if diff_fields.is_empty() {
- span_err!(tcx.sess,
- span,
- E0374,
- "the trait `CoerceUnsized` may only be implemented \
+ struct_span_err!(
+ tcx.sess,
+ span,
+ E0374,
+ "the trait `CoerceUnsized` may only be implemented \
for a coercion between structures with one field \
- being coerced, none found");
+ being coerced, none found"
+ )
+ .emit();
return err_info;
} else if diff_fields.len() > 1 {
- let item = tcx.hir.expect_item(impl_node_id);
- let span = if let ItemImpl(.., Some(ref t), _, _) = item.node {
+ let item = tcx.hir().expect_item(impl_hir_id);
+ let span = if let ItemKind::Impl { of_trait: Some(ref t), .. } = item.kind {
t.path.span
} else {
- tcx.hir.span(impl_node_id)
+ tcx.hir().span(impl_hir_id)
};
- let mut err = struct_span_err!(tcx.sess,
- span,
- E0375,
- "implementing the trait \
+ struct_span_err!(
+ tcx.sess,
+ span,
+ E0375,
+ "implementing the trait \
`CoerceUnsized` requires multiple \
- coercions");
- err.note("`CoerceUnsized` may only be implemented for \
- a coercion between structures with one field being coerced");
- err.note(&format!("currently, {} fields need coercions: {}",
- diff_fields.len(),
- diff_fields.iter()
- .map(|&(i, a, b)| {
- format!("{} ({} to {})", fields[i].name, a, b)
- })
- .collect::<Vec<_>>()
- .join(", ")));
- err.span_label(span, "requires multiple coercions");
- err.emit();
+ coercions"
+ )
+ .note(
+ "`CoerceUnsized` may only be implemented for \
+ a coercion between structures with one field being coerced",
+ )
+ .note(&format!(
+ "currently, {} fields need coercions: {}",
+ diff_fields.len(),
+ diff_fields
+ .iter()
+ .map(|&(i, a, b)| {
+ format!("`{}` (`{}` to `{}`)", fields[i].ident, a, b)
+ })
+ .collect::<Vec<_>>()
+ .join(", ")
+ ))
+ .span_label(span, "requires multiple coercions")
+ .emit();
return err_info;
}
}
_ => {
- span_err!(tcx.sess,
- span,
- E0376,
- "the trait `CoerceUnsized` may only be implemented \
- for a coercion between structures");
+ struct_span_err!(
+ tcx.sess,
+ span,
+ E0376,
+ "the trait `CoerceUnsized` may only be implemented \
+ for a coercion between structures"
+ )
+ .emit();
return err_info;
}
};
- let mut fulfill_cx = traits::FulfillmentContext::new();
+ let mut fulfill_cx = TraitEngine::new(infcx.tcx);
// Register an obligation for `A: Trait<B>`.
- let cause = traits::ObligationCause::misc(span, impl_node_id);
- let predicate = tcx.predicate_for_trait_def(param_env,
- cause,
- trait_def_id,
- 0,
- source,
- &[target]);
+ let cause = traits::ObligationCause::misc(span, impl_hir_id);
+ let predicate = predicate_for_trait_def(
+ tcx,
+ param_env,
+ cause,
+ trait_def_id,
+ 0,
+ source,
+ &[target.into()],
+ );
fulfill_cx.register_predicate_obligation(&infcx, predicate);
// Check that all transitive obligations are satisfied.
if let Err(errors) = fulfill_cx.select_all_or_error(&infcx) {
- infcx.report_fulfillment_errors(&errors, None);
+ infcx.report_fulfillment_errors(&errors, None, false);
}
// Finally, resolve all regions.
- let region_maps = RegionMaps::new();
- let mut free_regions = FreeRegionMap::new();
- free_regions.relate_free_regions_from_predicates(¶m_env.caller_bounds);
- infcx.resolve_regions_and_report_errors(impl_did, ®ion_maps, &free_regions);
+ let outlives_env = OutlivesEnvironment::new(param_env);
+ infcx.resolve_regions_and_report_errors(impl_did, &outlives_env, RegionckMode::default());
- CoerceUnsizedInfo {
- custom_kind: kind
- }
+ CoerceUnsizedInfo { custom_kind: kind }
})
}