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

Rollup of 6 pull requests #102896

Merged
merged 13 commits into from
Oct 11, 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
18 changes: 12 additions & 6 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2721,11 +2721,11 @@ checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"

[[package]]
name = "proc-macro2"
version = "1.0.37"
version = "1.0.46"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec757218438d5fda206afc041538b2f6d889286160d649a86a24d37e1235afd1"
checksum = "94e2ef8dbfc347b10c094890f778ee2e36ca9bb4262e86dc99cd217e35f3470b"
dependencies = [
"unicode-xid",
"unicode-ident",
]

[[package]]
Expand Down Expand Up @@ -4719,13 +4719,13 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"

[[package]]
name = "syn"
version = "1.0.91"
version = "1.0.102"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b683b2b825c8eef438b77c36a06dc262294da3d5a5813fac20da149241dcd44d"
checksum = "3fcd952facd492f9be3ef0d0b7032a6e442ee9b361d4acc2b1d0c4aaa5f613a1"
dependencies = [
"proc-macro2",
"quote",
"unicode-xid",
"unicode-ident",
]

[[package]]
Expand Down Expand Up @@ -5215,6 +5215,12 @@ dependencies = [
"matches",
]

[[package]]
name = "unicode-ident"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3"

[[package]]
name = "unicode-normalization"
version = "0.1.22"
Expand Down
18 changes: 17 additions & 1 deletion compiler/rustc_parse/src/parser/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1788,7 +1788,23 @@ impl<'a> Parser<'a> {
}
}
} else {
self.expected_ident_found()
let mut err = self.expected_ident_found();
if let Some((ident, _)) = self.token.ident() && ident.as_str() == "let" {
self.bump(); // `let`
let span = self.prev_token.span.until(self.token.span);
err.span_suggestion(
span,
"remove the let, the `let` keyword is not allowed in struct field definitions",
String::new(),
Applicability::MachineApplicable,
);
err.note("the `let` keyword is not allowed in `struct` fields");
err.note("see <https://doc.rust-lang.org/book/ch05-01-defining-structs.html> for more information");
err.emit();
self.bump();
return Ok(ident);
}
err
};
return Err(err);
}
Expand Down
38 changes: 36 additions & 2 deletions compiler/rustc_resolve/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ impl TypoSuggestion {
}

/// A free importable items suggested in case of resolution failure.
#[derive(Debug, Clone)]
pub(crate) struct ImportSuggestion {
pub did: Option<DefId>,
pub descr: &'static str,
Expand Down Expand Up @@ -139,6 +140,7 @@ impl<'a> Resolver<'a> {
if instead { Instead::Yes } else { Instead::No },
found_use,
IsPattern::No,
IsImport::No,
path,
);
err.emit();
Expand Down Expand Up @@ -698,6 +700,7 @@ impl<'a> Resolver<'a> {
Instead::No,
FoundUse::Yes,
IsPattern::Yes,
IsImport::No,
vec![],
);
}
Expand Down Expand Up @@ -1481,6 +1484,7 @@ impl<'a> Resolver<'a> {
Instead::No,
FoundUse::Yes,
IsPattern::No,
IsImport::No,
vec![],
);

Expand Down Expand Up @@ -2449,6 +2453,34 @@ enum IsPattern {
No,
}

/// Whether a binding is part of a use statement. Used for diagnostics.
enum IsImport {
Yes,
No,
}

pub(crate) fn import_candidates(
session: &Session,
source_span: &IndexVec<LocalDefId, Span>,
err: &mut Diagnostic,
// This is `None` if all placement locations are inside expansions
use_placement_span: Option<Span>,
candidates: &[ImportSuggestion],
) {
show_candidates(
session,
source_span,
err,
use_placement_span,
candidates,
Instead::Yes,
FoundUse::Yes,
IsPattern::No,
IsImport::Yes,
vec![],
);
}

/// When an entity with a given name is not available in scope, we search for
/// entities with that name in all crates. This method allows outputting the
/// results of this search in a programmer-friendly way
Expand All @@ -2462,6 +2494,7 @@ fn show_candidates(
instead: Instead,
found_use: FoundUse,
is_pattern: IsPattern,
is_import: IsImport,
path: Vec<Segment>,
) {
if candidates.is_empty() {
Expand Down Expand Up @@ -2521,7 +2554,8 @@ fn show_candidates(
// produce an additional newline to separate the new use statement
// from the directly following item.
let additional_newline = if let FoundUse::Yes = found_use { "" } else { "\n" };
candidate.0 = format!("use {};\n{}", &candidate.0, additional_newline);
let add_use = if let IsImport::Yes = is_import { "" } else { "use " };
candidate.0 = format!("{}{};\n{}", add_use, &candidate.0, additional_newline);
}

err.span_suggestions(
Expand Down Expand Up @@ -2551,7 +2585,7 @@ fn show_candidates(

err.note(&msg);
}
} else {
} else if matches!(is_import, IsImport::No) {
assert!(!inaccessible_path_strings.is_empty());

let prefix =
Expand Down
28 changes: 26 additions & 2 deletions compiler/rustc_resolve/src/imports.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
//! A bunch of methods and structures more or less related to resolving imports.

use crate::diagnostics::Suggestion;
use crate::diagnostics::{import_candidates, Suggestion};
use crate::Determinacy::{self, *};
use crate::Namespace::{self, *};
use crate::{module_to_string, names_to_string};
use crate::{module_to_string, names_to_string, ImportSuggestion};
use crate::{AmbiguityKind, BindingKey, ModuleKind, ResolutionError, Resolver, Segment};
use crate::{Finalize, Module, ModuleOrUniformRoot, ParentScope, PerNS, ScopeSet};
use crate::{NameBinding, NameBindingKind, PathResult};
Expand Down Expand Up @@ -406,6 +406,7 @@ struct UnresolvedImportError {
label: Option<String>,
note: Option<String>,
suggestion: Option<Suggestion>,
candidate: Option<Vec<ImportSuggestion>>,
}

pub struct ImportResolver<'a, 'b> {
Expand Down Expand Up @@ -497,6 +498,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
label: None,
note: None,
suggestion: None,
candidate: None,
};
if path.contains("::") {
errors.push((path, err))
Expand Down Expand Up @@ -547,6 +549,16 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
}
diag.multipart_suggestion(&msg, suggestions, applicability);
}

if let Some(candidate) = &err.candidate {
import_candidates(
self.r.session,
&self.r.source_span,
&mut diag,
Some(err.span),
&candidate,
)
}
}

diag.emit();
Expand Down Expand Up @@ -664,6 +676,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
Some(finalize),
ignore_binding,
);

let no_ambiguity = self.r.ambiguity_errors.len() == prev_ambiguity_errors_len;
import.vis.set(orig_vis);
let module = match path_res {
Expand Down Expand Up @@ -706,12 +719,14 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
String::from("a similar path exists"),
Applicability::MaybeIncorrect,
)),
candidate: None,
},
None => UnresolvedImportError {
span,
label: Some(label),
note: None,
suggestion,
candidate: None,
},
};
return Some(err);
Expand Down Expand Up @@ -754,6 +769,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
label: Some(String::from("cannot glob-import a module into itself")),
note: None,
suggestion: None,
candidate: None,
});
}
}
Expand Down Expand Up @@ -919,11 +935,19 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
}
};

let parent_suggestion =
self.r.lookup_import_candidates(ident, TypeNS, &import.parent_scope, |_| true);

Some(UnresolvedImportError {
span: import.span,
label: Some(label),
note,
suggestion,
candidate: if !parent_suggestion.is_empty() {
Some(parent_suggestion)
} else {
None
},
})
} else {
// `resolve_ident_in_module` reported a privacy error.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1255,6 +1255,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
found_span,
found_trait_ref,
expected_trait_ref,
obligation.cause.code(),
)
} else {
let (closure_span, found) = found_did
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -254,8 +254,15 @@ pub trait TypeErrCtxtExt<'tcx> {
found_span: Option<Span>,
found: ty::PolyTraitRef<'tcx>,
expected: ty::PolyTraitRef<'tcx>,
cause: &ObligationCauseCode<'tcx>,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>;

fn note_conflicting_closure_bounds(
&self,
cause: &ObligationCauseCode<'tcx>,
err: &mut DiagnosticBuilder<'tcx, ErrorGuaranteed>,
);

fn suggest_fully_qualified_path(
&self,
err: &mut Diagnostic,
Expand Down Expand Up @@ -1584,6 +1591,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
found_span: Option<Span>,
found: ty::PolyTraitRef<'tcx>,
expected: ty::PolyTraitRef<'tcx>,
cause: &ObligationCauseCode<'tcx>,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
pub(crate) fn build_fn_sig_ty<'tcx>(
infcx: &InferCtxt<'tcx>,
Expand Down Expand Up @@ -1645,9 +1653,68 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
let signature_kind = format!("{argument_kind} signature");
err.note_expected_found(&signature_kind, expected_str, &signature_kind, found_str);

self.note_conflicting_closure_bounds(cause, &mut err);

err
}

// Add a note if there are two `Fn`-family bounds that have conflicting argument
// requirements, which will always cause a closure to have a type error.
fn note_conflicting_closure_bounds(
&self,
cause: &ObligationCauseCode<'tcx>,
err: &mut DiagnosticBuilder<'tcx, ErrorGuaranteed>,
) {
// First, look for an `ExprBindingObligation`, which means we can get
// the unsubstituted predicate list of the called function. And check
// that the predicate that we failed to satisfy is a `Fn`-like trait.
if let ObligationCauseCode::ExprBindingObligation(def_id, _, _, idx) = cause
&& let predicates = self.tcx.predicates_of(def_id).instantiate_identity(self.tcx)
&& let Some(pred) = predicates.predicates.get(*idx)
&& let ty::PredicateKind::Trait(trait_pred) = pred.kind().skip_binder()
&& ty::ClosureKind::from_def_id(self.tcx, trait_pred.def_id()).is_some()
{
let expected_self =
self.tcx.anonymize_late_bound_regions(pred.kind().rebind(trait_pred.self_ty()));
let expected_substs = self
.tcx
.anonymize_late_bound_regions(pred.kind().rebind(trait_pred.trait_ref.substs));

// Find another predicate whose self-type is equal to the expected self type,
// but whose substs don't match.
let other_pred = std::iter::zip(&predicates.predicates, &predicates.spans)
.enumerate()
.find(|(other_idx, (pred, _))| match pred.kind().skip_binder() {
ty::PredicateKind::Trait(trait_pred)
if ty::ClosureKind::from_def_id(self.tcx, trait_pred.def_id())
.is_some()
&& other_idx != idx
// Make sure that the self type matches
// (i.e. constraining this closure)
&& expected_self
== self.tcx.anonymize_late_bound_regions(
pred.kind().rebind(trait_pred.self_ty()),
)
// But the substs don't match (i.e. incompatible args)
&& expected_substs
!= self.tcx.anonymize_late_bound_regions(
pred.kind().rebind(trait_pred.trait_ref.substs),
) =>
{
true
}
_ => false,
});
// If we found one, then it's very likely the cause of the error.
if let Some((_, (_, other_pred_span))) = other_pred {
err.span_note(
*other_pred_span,
"closure inferred to have a different signature due to this bound",
);
}
}
}

fn suggest_fully_qualified_path(
&self,
err: &mut Diagnostic,
Expand Down
8 changes: 4 additions & 4 deletions src/bootstrap/Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -445,9 +445,9 @@ dependencies = [

[[package]]
name = "proc-macro2"
version = "1.0.39"
version = "1.0.46"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f"
checksum = "94e2ef8dbfc347b10c094890f778ee2e36ca9bb4262e86dc99cd217e35f3470b"
dependencies = [
"unicode-ident",
]
Expand Down Expand Up @@ -596,9 +596,9 @@ dependencies = [

[[package]]
name = "syn"
version = "1.0.95"
version = "1.0.102"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fbaf6116ab8924f39d52792136fb74fd60a80194cf1b1c6ffa6453eef1c3f942"
checksum = "3fcd952facd492f9be3ef0d0b7032a6e442ee9b361d4acc2b1d0c4aaa5f613a1"
dependencies = [
"proc-macro2",
"quote",
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.12.0
0.12.2
Loading