Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

small method code cleanup #104890

Merged
merged 4 commits into from
Nov 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 10 additions & 6 deletions compiler/rustc_hir_typeck/src/callee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
12 changes: 0 additions & 12 deletions compiler/rustc_hir_typeck/src/cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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) => {
Expand All @@ -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.
Expand Down
35 changes: 6 additions & 29 deletions compiler/rustc_hir_typeck/src/coercion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,10 +199,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");
}
Expand Down Expand Up @@ -507,27 +503,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<B> for A` where
// A and B have 'matching' fields. This rules out the following
// two types of blanket impls:
//
// `impl<T> CoerceUnsized<T> for SomeType`
// `impl<T> CoerceUnsized<SomeType> 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<T> CoerceUnsized<SomeType> for T`)
// or generic over the `CoerceUnsized` type parameter (`impl<T> CoerceUnsized<T> 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);
Expand Down Expand Up @@ -1112,15 +1090,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()) {
Expand Down
9 changes: 4 additions & 5 deletions compiler/rustc_hir_typeck/src/method/probe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -342,10 +342,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
Expand Down Expand Up @@ -374,7 +373,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
opt_bad_ty: None,
reached_recursion_limit: false,
}
})
}),
};

// If our autoderef loop had reached the recursion limit,
Expand Down
62 changes: 26 additions & 36 deletions compiler/rustc_infer/src/infer/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1677,40 +1677,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) => (
Expand Down Expand Up @@ -1880,9 +1874,6 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
);
}
}
TypeError::ObjectUnsafeCoercion(_) => {
diag.note_unsuccessful_coercion(found, expected);
}
_ => {
debug!(
"note_type_err: exp_found={:?}, expected={:?} found={:?}",
Expand Down Expand Up @@ -3127,7 +3118,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"),
},
}
Expand Down
5 changes: 1 addition & 4 deletions compiler/rustc_middle/src/ty/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@ pub enum TypeError<'tcx> {
CyclicConst(ty::Const<'tcx>),
ProjectionMismatched(ExpectedFound<DefId>),
ExistentialMismatch(ExpectedFound<&'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>>),
ObjectUnsafeCoercion(DefId),
ConstMismatch(ExpectedFound<ty::Const<'tcx>>),

IntrinsicCast,
Expand Down Expand Up @@ -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"),
}
}
}
Expand All @@ -249,8 +247,7 @@ impl<'tcx> TypeError<'tcx> {
| ProjectionMismatched(_)
| ExistentialMismatch(_)
| ConstMismatch(_)
| IntrinsicCast
| ObjectUnsafeCoercion(_) => true,
| IntrinsicCast => true,
}
}
}
Expand Down