diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index 1c14c1d35f799..e50d249849fa8 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -179,12 +179,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Hack: we know that there are traits implementing Fn for &F // where F:Fn and so forth. In the particular case of types - // like `x: &mut FnMut()`, if there is a call `x()`, we would - // normally translate to `FnMut::call_mut(&mut x, ())`, but - // that winds up requiring `mut x: &mut FnMut()`. A little - // over the top. The simplest fix by far is to just ignore - // this case and deref again, so we wind up with - // `FnMut::call_mut(&mut *x, ())`. + // like `f: &mut FnMut()`, if there is a call `f()`, we would + // normally translate to `FnMut::call_mut(&mut f, ())`, but + // that winds up potentially requiring the user to mark their + // variable as `mut` which feels unnecessary and unexpected. + // + // fn foo(f: &mut impl FnMut()) { f() } + // ^ without this hack `f` would have to be declared as mutable + // + // The simplest fix by far is to just ignore this case and deref again, + // so we wind up with `FnMut::call_mut(&mut *f, ())`. ty::Ref(..) if autoderef.step_count() == 0 => { return None; } diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index 1cea8c9dadce3..732b4bec58ed5 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -46,7 +46,6 @@ use rustc_span::def_id::{DefId, LOCAL_CRATE}; use rustc_span::symbol::sym; use rustc_span::Span; use rustc_trait_selection::infer::InferCtxtExt; -use rustc_trait_selection::traits::error_reporting::report_object_safety_error; /// Reifies a cast check to be checked once we have full type information for /// a function context. @@ -727,9 +726,6 @@ impl<'a, 'tcx> CastCheck<'tcx> { debug!(" -> CoercionCast"); fcx.typeck_results.borrow_mut().set_coercion_cast(self.expr.hir_id.local_id); } - Err(ty::error::TypeError::ObjectUnsafeCoercion(did)) => { - self.report_object_unsafe_cast(&fcx, did); - } Err(_) => { match self.do_check(fcx) { Ok(k) => { @@ -741,14 +737,6 @@ impl<'a, 'tcx> CastCheck<'tcx> { }; } } - - fn report_object_unsafe_cast(&self, fcx: &FnCtxt<'a, 'tcx>, did: DefId) { - let violations = fcx.tcx.object_safety_violations(did); - let mut err = report_object_safety_error(fcx.tcx, self.cast_span, did, violations); - err.note(&format!("required by cast to type '{}'", fcx.ty_to_string(self.cast_ty))); - err.emit(); - } - /// Checks a cast, and report an error if one exists. In some cases, this /// can return Ok and create type errors in the fcx rather than returning /// directly. coercion-cast is handled in check instead of here. diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 6b6d54db5062f..b2d9d70fbd2ac 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -195,10 +195,6 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { debug!("coerce: unsize successful"); return unsize; } - Err(TypeError::ObjectUnsafeCoercion(did)) => { - debug!("coerce: unsize not object safe"); - return Err(TypeError::ObjectUnsafeCoercion(did)); - } Err(error) => { debug!(?error, "coerce: unsize failed"); } @@ -498,27 +494,9 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { target = self.shallow_resolve(target); debug!(?source, ?target); - // These 'if' statements require some explanation. - // The `CoerceUnsized` trait is special - it is only - // possible to write `impl CoerceUnsized for A` where - // A and B have 'matching' fields. This rules out the following - // two types of blanket impls: - // - // `impl CoerceUnsized for SomeType` - // `impl CoerceUnsized for T` - // - // Both of these trigger a special `CoerceUnsized`-related error (E0376) - // - // We can take advantage of this fact to avoid performing unnecessary work. - // If either `source` or `target` is a type variable, then any applicable impl - // would need to be generic over the self-type (`impl CoerceUnsized for T`) - // or generic over the `CoerceUnsized` type parameter (`impl CoerceUnsized for - // SomeType`). - // - // However, these are exactly the kinds of impls which are forbidden by - // the compiler! Therefore, we can be sure that coercion will always fail - // when either the source or target type is a type variable. This allows us - // to skip performing any trait selection, and immediately bail out. + // We don't apply any coercions incase either the source or target + // aren't sufficiently well known but tend to instead just equate + // them both. if source.is_ty_var() { debug!("coerce_unsized: source is a TyVar, bailing out"); return Err(TypeError::Mismatch); @@ -1101,15 +1079,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Special-case that coercion alone cannot handle: // Function items or non-capturing closures of differing IDs or InternalSubsts. let (a_sig, b_sig) = { - #[allow(rustc::usage_of_ty_tykind)] - let is_capturing_closure = |ty: &ty::TyKind<'tcx>| { - if let &ty::Closure(closure_def_id, _substs) = ty { + let is_capturing_closure = |ty: Ty<'tcx>| { + if let &ty::Closure(closure_def_id, _substs) = ty.kind() { self.tcx.upvars_mentioned(closure_def_id.expect_local()).is_some() } else { false } }; - if is_capturing_closure(prev_ty.kind()) || is_capturing_closure(new_ty.kind()) { + if is_capturing_closure(prev_ty) || is_capturing_closure(new_ty) { (None, None) } else { match (prev_ty.kind(), new_ty.kind()) { diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 6d858eacb45a3..4380e66a0d248 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -343,10 +343,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &mut orig_values, ); - let steps = if mode == Mode::MethodCall { - self.tcx.method_autoderef_steps(param_env_and_self_ty) - } else { - self.probe(|_| { + let steps = match mode { + Mode::MethodCall => self.tcx.method_autoderef_steps(param_env_and_self_ty), + Mode::Path => self.probe(|_| { // Mode::Path - the deref steps is "trivial". This turns // our CanonicalQuery into a "trivial" QueryResponse. This // is a bit inefficient, but I don't think that writing @@ -375,7 +374,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { opt_bad_ty: None, reached_recursion_limit: false, } - }) + }), }; // If our autoderef loop had reached the recursion limit, diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 6b6be7359a599..e2be8fb12d0d0 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -1672,40 +1672,34 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } }; - match terr { - // Ignore msg for object safe coercion - // since E0038 message will be printed - TypeError::ObjectUnsafeCoercion(_) => {} - _ => { - let mut label_or_note = |span: Span, msg: &str| { - if (prefer_label && is_simple_error) || &[span] == diag.span.primary_spans() { - diag.span_label(span, msg); - } else { - diag.span_note(span, msg); - } - }; - if let Some((sp, msg)) = secondary_span { - if swap_secondary_and_primary { - let terr = if let Some(infer::ValuePairs::Terms(infer::ExpectedFound { - expected, - .. - })) = values - { - format!("expected this to be `{}`", expected) - } else { - terr.to_string() - }; - label_or_note(sp, &terr); - label_or_note(span, &msg); - } else { - label_or_note(span, &terr.to_string()); - label_or_note(sp, &msg); - } - } else { - label_or_note(span, &terr.to_string()); - } + let mut label_or_note = |span: Span, msg: &str| { + if (prefer_label && is_simple_error) || &[span] == diag.span.primary_spans() { + diag.span_label(span, msg); + } else { + diag.span_note(span, msg); } }; + if let Some((sp, msg)) = secondary_span { + if swap_secondary_and_primary { + let terr = if let Some(infer::ValuePairs::Terms(infer::ExpectedFound { + expected, + .. + })) = values + { + format!("expected this to be `{}`", expected) + } else { + terr.to_string() + }; + label_or_note(sp, &terr); + label_or_note(span, &msg); + } else { + label_or_note(span, &terr.to_string()); + label_or_note(sp, &msg); + } + } else { + label_or_note(span, &terr.to_string()); + } + if let Some((expected, found)) = expected_found { let (expected_label, found_label, exp_found) = match exp_found { Mismatch::Variable(ef) => ( @@ -1875,9 +1869,6 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { ); } } - TypeError::ObjectUnsafeCoercion(_) => { - diag.note_unsuccessful_coercion(found, expected); - } _ => { debug!( "note_type_err: exp_found={:?}, expected={:?} found={:?}", @@ -3122,7 +3113,6 @@ impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> { TypeError::IntrinsicCast => { Error0308("cannot coerce intrinsics to function pointers") } - TypeError::ObjectUnsafeCoercion(did) => Error0038(did), _ => Error0308("mismatched types"), }, } diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index a61f41b9c580f..d83e17574a094 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -70,7 +70,6 @@ pub enum TypeError<'tcx> { CyclicConst(ty::Const<'tcx>), ProjectionMismatched(ExpectedFound), ExistentialMismatch(ExpectedFound<&'tcx ty::List>>), - ObjectUnsafeCoercion(DefId), ConstMismatch(ExpectedFound>), IntrinsicCast, @@ -222,7 +221,6 @@ impl<'tcx> fmt::Display for TypeError<'tcx> { f, "cannot coerce functions with `#[target_feature]` to safe function pointers" ), - ObjectUnsafeCoercion(_) => write!(f, "coercion to object-unsafe trait object"), } } } @@ -249,8 +247,7 @@ impl<'tcx> TypeError<'tcx> { | ProjectionMismatched(_) | ExistentialMismatch(_) | ConstMismatch(_) - | IntrinsicCast - | ObjectUnsafeCoercion(_) => true, + | IntrinsicCast => true, } } }