Remove Session.trait_methods_not_found

Instead, avoid registering the problematic well-formed obligation
to begin with. This removes global untracked mutable state,
and avoids potential issues with incremental compilation.
This commit is contained in:
Aaron Hill 2021-08-21 18:45:56 -05:00
parent b6e334d873
commit 41f9f38d6e
No known key found for this signature in database
GPG key ID: B4087E510E98B164
4 changed files with 23 additions and 15 deletions

View file

@ -104,11 +104,5 @@ pub fn report_object_safety_error(
to be resolvable dynamically; for more information visit \
<https://doc.rust-lang.org/reference/items/traits.html#object-safety>",
);
if tcx.sess.trait_methods_not_found.borrow().iter().any(|full_span| full_span.contains(span)) {
// Avoid emitting error caused by non-existing method (#58734)
err.cancel();
}
err
}

View file

@ -189,9 +189,6 @@ pub struct Session {
/// Cap lint level specified by a driver specifically.
pub driver_lint_caps: FxHashMap<lint::LintId, lint::Level>,
/// `Span`s of trait methods that weren't found to avoid emitting object safety errors
pub trait_methods_not_found: Lock<FxHashSet<Span>>,
/// Mapping from ident span to path span for paths that don't exist as written, but that
/// exist under `std`. For example, wrote `str::from_utf8` instead of `std::str::from_utf8`.
pub confused_type_with_std_module: Lock<FxHashMap<Span, Span>>,
@ -1353,7 +1350,6 @@ pub fn build_session(
print_fuel,
jobserver: jobserver::client(),
driver_lint_caps,
trait_methods_not_found: Lock::new(Default::default()),
confused_type_with_std_module: Lock::new(Default::default()),
ctfe_backtrace,
miri_unleashed_features: Lock::new(Default::default()),

View file

@ -858,13 +858,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
path.segments,
);
}
QPath::TypeRelative(ref qself, ref segment) => (self.to_ty(qself), qself, segment),
QPath::TypeRelative(ref qself, ref segment) => {
// Don't use `self.to_ty`, since this will register a WF obligation.
// If we're trying to call a non-existent method on a trait
// (e.g. `MyTrait::missing_method`), then resolution will
// give us a `QPath::TypeRelative` with a trait object as
// `qself`. In that case, we want to avoid registering a WF obligation
// for `dyn MyTrait`, since we don't actually need the trait
// to be object-safe.
// We manually call `register_wf_obligation` in the success path
// below.
(<dyn AstConv<'_>>::ast_ty_to_ty(self, qself), qself, segment)
}
QPath::LangItem(..) => {
bug!("`resolve_ty_and_res_fully_qualified_call` called on `LangItem`")
}
};
if let Some(&cached_result) = self.typeck_results.borrow().type_dependent_defs().get(hir_id)
{
self.register_wf_obligation(ty.into(), qself.span, traits::WellFormed(None));
// Return directly on cache hit. This is useful to avoid doubly reporting
// errors with default match binding modes. See #44614.
let def = cached_result.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id));
@ -878,6 +890,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
method::MethodError::PrivateMatch(kind, def_id, _) => Ok((kind, def_id)),
_ => Err(ErrorReported),
};
// If we have a path like `MyTrait::missing_method`, then don't register
// a WF obligation for `dyn MyTrait` when method lookup fails. Otherwise,
// register a WF obligation so that we can detect any additional
// errors in the self type.
if !(matches!(error, method::MethodError::NoMatch(_)) && ty.is_trait()) {
self.register_wf_obligation(ty.into(), qself.span, traits::WellFormed(None));
}
if item_name.name != kw::Empty {
if let Some(mut e) = self.report_method_error(
span,
@ -895,6 +915,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if result.is_ok() {
self.maybe_lint_bare_trait(qpath, hir_id);
self.register_wf_obligation(ty.into(), qself.span, traits::WellFormed(None));
}
// Write back the new resolution.

View file

@ -70,15 +70,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pub fn report_method_error(
&self,
span: Span,
mut span: Span,
rcvr_ty: Ty<'tcx>,
item_name: Ident,
source: SelfSource<'tcx>,
error: MethodError<'tcx>,
args: Option<&'tcx [hir::Expr<'tcx>]>,
) -> Option<DiagnosticBuilder<'_>> {
let orig_span = span;
let mut span = span;
// Avoid suggestions when we don't know what's going on.
if rcvr_ty.references_error() {
return None;
@ -545,7 +543,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} else {
err.span_label(span, format!("{item_kind} cannot be called on `{ty_str}` due to unsatisfied trait bounds"));
}
self.tcx.sess.trait_methods_not_found.borrow_mut().insert(orig_span);
};
// If the method name is the name of a field with a function or closure type,