parent
caa64e5b5e
commit
c9381fc334
5 changed files with 135 additions and 7 deletions
|
@ -16,7 +16,7 @@ use rustc_ast::ptr::P;
|
|||
use rustc_ast::visit::{self, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor};
|
||||
use rustc_ast::*;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
|
||||
use rustc_errors::{DiagnosticArgValue, DiagnosticId, IntoDiagnosticArg};
|
||||
use rustc_errors::{Applicability, DiagnosticArgValue, DiagnosticId, IntoDiagnosticArg};
|
||||
use rustc_hir::def::Namespace::{self, *};
|
||||
use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, PartialRes, PerNS};
|
||||
use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
|
||||
|
@ -536,6 +536,9 @@ struct DiagnosticMetadata<'ast> {
|
|||
in_assignment: Option<&'ast Expr>,
|
||||
is_assign_rhs: bool,
|
||||
|
||||
/// Used to detect possible `.` -> `..` typo when calling methods.
|
||||
in_range: Option<(&'ast Expr, &'ast Expr)>,
|
||||
|
||||
/// If we are currently in a trait object definition. Used to point at the bounds when
|
||||
/// encountering a struct or enum.
|
||||
current_trait_object: Option<&'ast [ast::GenericBound]>,
|
||||
|
@ -3320,6 +3323,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
|||
);
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn smart_resolve_path_fragment(
|
||||
&mut self,
|
||||
qself: &Option<P<QSelf>>,
|
||||
|
@ -3327,10 +3331,6 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
|||
source: PathSource<'ast>,
|
||||
finalize: Finalize,
|
||||
) -> PartialRes {
|
||||
debug!(
|
||||
"smart_resolve_path_fragment(qself={:?}, path={:?}, finalize={:?})",
|
||||
qself, path, finalize,
|
||||
);
|
||||
let ns = source.namespace();
|
||||
|
||||
let Finalize { node_id, path_span, .. } = finalize;
|
||||
|
@ -3341,8 +3341,20 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
|||
|
||||
let def_id = this.parent_scope.module.nearest_parent_mod();
|
||||
let instead = res.is_some();
|
||||
let suggestion =
|
||||
if res.is_none() { this.report_missing_type_error(path) } else { None };
|
||||
let suggestion = if let Some((start, end)) = this.diagnostic_metadata.in_range
|
||||
&& path[0].ident.span.lo() == end.span.lo()
|
||||
{
|
||||
Some((
|
||||
start.span.between(end.span),
|
||||
"you might have meant to write a method call instead of a range",
|
||||
".".to_string(),
|
||||
Applicability::MaybeIncorrect,
|
||||
))
|
||||
} else if res.is_none() {
|
||||
this.report_missing_type_error(path)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
this.r.use_injections.push(UseError {
|
||||
err,
|
||||
|
@ -4005,6 +4017,12 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
|||
self.visit_expr(rhs);
|
||||
self.diagnostic_metadata.is_assign_rhs = false;
|
||||
}
|
||||
ExprKind::Range(Some(ref start), Some(ref end), RangeLimits::HalfOpen) => {
|
||||
self.diagnostic_metadata.in_range = Some((start, end));
|
||||
self.resolve_expr(start, Some(expr));
|
||||
self.resolve_expr(end, Some(expr));
|
||||
self.diagnostic_metadata.in_range = None;
|
||||
}
|
||||
_ => {
|
||||
visit::walk_expr(self, expr);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue