From d8d57f56dabb1ca31a66613b2318ffaa66122ba4 Mon Sep 17 00:00:00 2001 From: Ayush Kumar Mishra Date: Wed, 3 Jun 2020 20:16:08 +0530 Subject: [PATCH] Remove noisy suggestion of hash_map #72642 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update src/librustc_resolve/diagnostics.rs Co-authored-by: David Wood Minor refactoring #72642 Fixed failing test-cases remove trivial `mk_predicate`s Make `SourceMap` available for early debug-printing of `Span`s Normally, we debug-print `Spans` using the `SourceMap` retrieved from the global `TyCtxt`. However, we fall back to printing out the `Span`'s raw fields (instead of a file and line number) when we try to print a `Span` before a `TyCtxt` is available. This makes debugging early phases of the compile, such as parsing, much more difficult. This commit stores a `SourceMap` in `rustc_span::GlOBALS` as a fallback. When a `TyCtxt` is not available, we try to retrieve one from `GLOBALS` - only if this is not available do we fall back to the raw field output. I'm not sure how to write a test for this - however, this can be verified locally by setting `RUSTC_LOG="rustc_parse=debug"`, and verifying that the output contains filenames and line numbers. Add test for #72554. rustc_target: Remove `pre_link_args_crt` Improve E0433, so that it suggests missing imports Fix a typo in `late.rs` Co-authored-by: Esteban Kuber fix `AdtDef` docs Add Camelid Email from @camelid: > HI there, > > I’m a new contributor and I just looked at Rust Thanks and noticed that my contributions are listed under two different capitalizations of my name: “Camelid" and “camelid". Could you make them both “Camelid"? > > Thanks! > > Camelid save_analysis: work on HIR tree instead of AST Update `rls` submodule remove outdated fixme Hexagon libstd: fix typo for c_ulonglong Add more assert to Vec with_capacity docs Show assertion on len too to show them how adding new items will affect both the length and capacity, before and after. Add Kyle Strand to mailmap Fix missing word in RELEASES.md Update cargo Enable lld for Cargo tests on Windows. Fixed failing test-cases #72642 --- .github/workflows/ci.yml | 2 +- .mailmap | 5 + RELEASES.md | 2 +- src/ci/azure-pipelines/auto.yml | 2 +- src/ci/github-actions/ci.yml | 2 +- src/liballoc/vec.rs | 3 + src/librustc_codegen_ssa/back/link.rs | 14 +- src/librustc_codegen_ssa/back/linker.rs | 15 + src/librustc_driver/lib.rs | 16 +- src/librustc_hir_pretty/lib.rs | 24 + src/librustc_interface/interface.rs | 24 +- src/librustc_middle/ty/mod.rs | 2 +- src/librustc_middle/ty/structural_impls.rs | 3 +- src/librustc_resolve/diagnostics.rs | 15 +- src/librustc_resolve/late.rs | 146 ++- src/librustc_resolve/lib.rs | 14 +- src/librustc_save_analysis/dump_visitor.rs | 916 ++++++++---------- src/librustc_save_analysis/lib.rs | 473 +++++---- src/librustc_save_analysis/sig.rs | 471 ++++----- src/librustc_span/lib.rs | 45 +- src/librustc_target/spec/mod.rs | 6 +- src/librustc_target/spec/tests/tests_impl.rs | 1 - src/librustc_target/spec/vxworks_base.rs | 3 - src/librustc_trait_selection/opaque_types.rs | 3 - src/libstd/os/linux/raw.rs | 2 +- .../ui/derived-errors/issue-31997-1.stderr | 7 +- src/test/ui/error-codes/E0433.rs | 2 +- src/test/ui/error-codes/E0433.stderr | 6 +- .../ui/hygiene/no_implicit_prelude.stderr | 6 +- src/test/ui/issues/issue-17546.stderr | 10 +- src/test/ui/issues/issue-72554.rs | 20 + src/test/ui/issues/issue-72554.stderr | 13 + src/test/ui/no-implicit-prelude-nested.stderr | 48 +- src/test/ui/no-implicit-prelude.stderr | 16 +- src/test/ui/resolve/use_suggestion.rs | 7 + src/test/ui/resolve/use_suggestion.stderr | 38 + .../resolve/use_suggestion_placement.stderr | 4 +- src/tools/cargo | 2 +- src/tools/rls | 2 +- 39 files changed, 1238 insertions(+), 1152 deletions(-) create mode 100644 src/test/ui/issues/issue-72554.rs create mode 100644 src/test/ui/issues/issue-72554.stderr create mode 100644 src/test/ui/resolve/use_suggestion.rs create mode 100644 src/test/ui/resolve/use_suggestion.stderr diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 291dbf603612a..c3c95226aebf6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -442,7 +442,7 @@ jobs: - name: x86_64-msvc-cargo env: SCRIPT: python x.py test src/tools/cargotest src/tools/cargo - RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc" + RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --enable-lld" VCVARS_BAT: vcvars64.bat NO_DEBUG_ASSERTIONS: 1 NO_LLVM_ASSERTIONS: 1 diff --git a/.mailmap b/.mailmap index da17344c2085e..9639c1174964c 100644 --- a/.mailmap +++ b/.mailmap @@ -44,6 +44,7 @@ Brian Anderson Brian Anderson Brian Dawn Brian Leibig Brian Leibig +Camelid <37223377+camelid@users.noreply.github.com> Carl-Anton Ingmarsson Carol (Nichols || Goulding) <193874+carols10cents@users.noreply.github.com> Carol (Nichols || Goulding) @@ -152,6 +153,10 @@ Kang Seonghoon Keegan McAllister Kevin Butler Kyeongwoon Lee +Kyle J Strand +Kyle J Strand +Kyle J Strand +Kyle J Strand Laurențiu Nicola Lee Jeffery Lee Jeffery Lee Wondong diff --git a/RELEASES.md b/RELEASES.md index fc9628bb365b4..8d6535b20c2eb 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -100,7 +100,7 @@ Compatibility Notes - [Removed the `-C no_integrated_as` flag from rustc.][70345] - [The `file_name` property in JSON output of macro errors now points the actual source file rather than the previous format of ``.][70969] - **Note:** this may not point a file that actually exists on the user's system. + **Note:** this may not point to a file that actually exists on the user's system. - [The minimum required external LLVM version has been bumped to LLVM 8.][71147] - [`mem::{zeroed, uninitialised}` will now panic when used with types that do not allow zero initialization such as `NonZeroU8`.][66059] This was diff --git a/src/ci/azure-pipelines/auto.yml b/src/ci/azure-pipelines/auto.yml index 46d3cf7a38ca2..f8fa7b727d179 100644 --- a/src/ci/azure-pipelines/auto.yml +++ b/src/ci/azure-pipelines/auto.yml @@ -148,7 +148,7 @@ jobs: INITIAL_RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc x86_64-msvc-cargo: SCRIPT: python x.py test src/tools/cargotest src/tools/cargo - INITIAL_RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc + INITIAL_RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-lld VCVARS_BAT: vcvars64.bat # FIXME(#59637) NO_DEBUG_ASSERTIONS: 1 diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml index 1c120f8163459..92fec593a5410 100644 --- a/src/ci/github-actions/ci.yml +++ b/src/ci/github-actions/ci.yml @@ -505,7 +505,7 @@ jobs: - name: x86_64-msvc-cargo env: SCRIPT: python x.py test src/tools/cargotest src/tools/cargo - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-lld VCVARS_BAT: vcvars64.bat # FIXME(#59637) NO_DEBUG_ASSERTIONS: 1 diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 22d43468771b4..ffae3b5c7894f 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -343,15 +343,18 @@ impl Vec { /// /// // The vector contains no items, even though it has capacity for more /// assert_eq!(vec.len(), 0); + /// assert_eq!(vec.capacity(), 10); /// /// // These are all done without reallocating... /// for i in 0..10 { /// vec.push(i); /// } + /// assert_eq!(vec.len(), 10); /// assert_eq!(vec.capacity(), 10); /// /// // ...but this may make the vector reallocate /// vec.push(11); + /// assert_eq!(vec.len(), 11); /// assert!(vec.capacity() >= 11); /// ``` #[inline] diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index dcce1d45298cc..cff84b11aa098 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -1253,20 +1253,10 @@ fn add_post_link_objects( /// Add arbitrary "pre-link" args defined by the target spec or from command line. /// FIXME: Determine where exactly these args need to be inserted. -fn add_pre_link_args( - cmd: &mut dyn Linker, - sess: &Session, - flavor: LinkerFlavor, - crate_type: CrateType, -) { +fn add_pre_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) { if let Some(args) = sess.target.target.options.pre_link_args.get(&flavor) { cmd.args(args); } - if let Some(args) = sess.target.target.options.pre_link_args_crt.get(&flavor) { - if sess.crt_static(Some(crate_type)) { - cmd.args(args); - } - } cmd.args(&sess.opts.debugging_opts.pre_link_args); } @@ -1502,7 +1492,7 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>( let crt_objects_fallback = crt_objects_fallback(sess, crate_type); // NO-OPT-OUT, OBJECT-FILES-MAYBE, CUSTOMIZATION-POINT - add_pre_link_args(cmd, sess, flavor, crate_type); + add_pre_link_args(cmd, sess, flavor); // NO-OPT-OUT add_link_script(cmd, sess, tmpdir, crate_type); diff --git a/src/librustc_codegen_ssa/back/linker.rs b/src/librustc_codegen_ssa/back/linker.rs index 77cb31bf3d278..d9fed998c92fb 100644 --- a/src/librustc_codegen_ssa/back/linker.rs +++ b/src/librustc_codegen_ssa/back/linker.rs @@ -315,6 +315,21 @@ impl<'a> Linker for GccLinker<'a> { self.build_dylib(out_filename); } } + // VxWorks compiler driver introduced `--static-crt` flag specifically for rustc, + // it switches linking for libc and similar system libraries to static without using + // any `#[link]` attributes in the `libc` crate, see #72782 for details. + // FIXME: Switch to using `#[link]` attributes in the `libc` crate + // similarly to other targets. + if self.sess.target.target.target_os == "vxworks" + && matches!( + output_kind, + LinkOutputKind::StaticNoPicExe + | LinkOutputKind::StaticPicExe + | LinkOutputKind::StaticDylib + ) + { + self.cmd.arg("--static-crt"); + } } fn link_dylib(&mut self, lib: Symbol) { diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 68ce93d3db90f..ccea041699ee1 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -346,12 +346,15 @@ pub fn run_compiler( queries.global_ctxt()?; + // Drop AST after creating GlobalCtxt to free memory + let _timer = sess.prof.generic_activity("drop_ast"); + mem::drop(queries.expansion()?.take()); + if sess.opts.debugging_opts.no_analysis || sess.opts.debugging_opts.ast_json { return early_exit(); } if sess.opts.debugging_opts.save_analysis { - let expanded_crate = &queries.expansion()?.peek().0; let crate_name = queries.crate_name()?.peek().clone(); queries.global_ctxt()?.peek_mut().enter(|tcx| { let result = tcx.analysis(LOCAL_CRATE); @@ -359,7 +362,6 @@ pub fn run_compiler( sess.time("save_analysis", || { save::process_crate( tcx, - &expanded_crate, &crate_name, &compiler.input(), None, @@ -371,13 +373,7 @@ pub fn run_compiler( }); result - // AST will be dropped *after* the `after_analysis` callback - // (needed by the RLS) })?; - } else { - // Drop AST after creating GlobalCtxt to free memory - let _timer = sess.prof.generic_activity("drop_ast"); - mem::drop(queries.expansion()?.take()); } queries.global_ctxt()?.peek_mut().enter(|tcx| tcx.analysis(LOCAL_CRATE))?; @@ -386,10 +382,6 @@ pub fn run_compiler( return early_exit(); } - if sess.opts.debugging_opts.save_analysis { - mem::drop(queries.expansion()?.take()); - } - queries.ongoing_codegen()?; if sess.opts.debugging_opts.print_type_sizes { diff --git a/src/librustc_hir_pretty/lib.rs b/src/librustc_hir_pretty/lib.rs index 8eb19cbb65a0a..e642915b86a5e 100644 --- a/src/librustc_hir_pretty/lib.rs +++ b/src/librustc_hir_pretty/lib.rs @@ -203,6 +203,30 @@ pub fn visibility_qualified>>(vis: &hir::Visibility<'_ }) } +pub fn generic_params_to_string(generic_params: &[GenericParam<'_>]) -> String { + to_string(NO_ANN, |s| s.print_generic_params(generic_params)) +} + +pub fn bounds_to_string<'b>(bounds: impl IntoIterator>) -> String { + to_string(NO_ANN, |s| s.print_bounds("", bounds)) +} + +pub fn param_to_string(arg: &hir::Param<'_>) -> String { + to_string(NO_ANN, |s| s.print_param(arg)) +} + +pub fn ty_to_string(ty: &hir::Ty<'_>) -> String { + to_string(NO_ANN, |s| s.print_type(ty)) +} + +pub fn path_segment_to_string(segment: &hir::PathSegment<'_>) -> String { + to_string(NO_ANN, |s| s.print_path_segment(segment)) +} + +pub fn path_to_string(segment: &hir::Path<'_>) -> String { + to_string(NO_ANN, |s| s.print_path(segment, false)) +} + impl<'a> State<'a> { pub fn cbox(&mut self, u: usize) { self.s.cbox(u); diff --git a/src/librustc_interface/interface.rs b/src/librustc_interface/interface.rs index f127a239eea2c..5aad64f84cee3 100644 --- a/src/librustc_interface/interface.rs +++ b/src/librustc_interface/interface.rs @@ -186,17 +186,19 @@ pub fn run_compiler_in_existing_thread_pool( override_queries: config.override_queries, }; - let r = { - let _sess_abort_error = OnDrop(|| { - compiler.sess.finish_diagnostics(registry); - }); - - f(&compiler) - }; - - let prof = compiler.sess.prof.clone(); - prof.generic_activity("drop_compiler").run(move || drop(compiler)); - r + rustc_span::with_source_map(compiler.sess.parse_sess.clone_source_map(), move || { + let r = { + let _sess_abort_error = OnDrop(|| { + compiler.sess.finish_diagnostics(registry); + }); + + f(&compiler) + }; + + let prof = compiler.sess.prof.clone(); + prof.generic_activity("drop_compiler").run(move || drop(compiler)); + r + }) } pub fn run_compiler(mut config: Config, f: impl FnOnce(&Compiler) -> R + Send) -> R { diff --git a/src/librustc_middle/ty/mod.rs b/src/librustc_middle/ty/mod.rs index a34cff06bc1cd..00c00a63b6b5d 100644 --- a/src/librustc_middle/ty/mod.rs +++ b/src/librustc_middle/ty/mod.rs @@ -1846,7 +1846,7 @@ pub struct FieldDef { /// The definition of a user-defined type, e.g., a `struct`, `enum`, or `union`. /// -/// These are all interned (by `intern_adt_def`) into the `adt_defs` table. +/// These are all interned (by `alloc_adt_def`) into the global arena. /// /// The initialism *ADT* stands for an [*algebraic data type (ADT)*][adt]. /// This is slightly wrong because `union`s are not ADTs. diff --git a/src/librustc_middle/ty/structural_impls.rs b/src/librustc_middle/ty/structural_impls.rs index cee0afacb68f7..f6f5dfd651612 100644 --- a/src/librustc_middle/ty/structural_impls.rs +++ b/src/librustc_middle/ty/structural_impls.rs @@ -987,7 +987,8 @@ impl<'tcx> TypeFoldable<'tcx> for ty::Region<'tcx> { impl<'tcx> TypeFoldable<'tcx> for ty::Predicate<'tcx> { fn super_fold_with>(&self, folder: &mut F) -> Self { - folder.tcx().mk_predicate(ty::PredicateKind::super_fold_with(self.kind, folder)) + let new = ty::PredicateKind::super_fold_with(self.kind, folder); + if new != *self.kind { folder.tcx().mk_predicate(new) } else { *self } } fn super_visit_with>(&self, visitor: &mut V) -> bool { diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index ea237f1a04f99..59fadfc41b06e 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -680,7 +680,9 @@ impl<'a> Resolver<'a> { Res::Def(DefKind::Ctor(..), did) => this.parent(did), _ => res.opt_def_id(), }; - candidates.push(ImportSuggestion { did, descr: res.descr(), path }); + if candidates.iter().all(|v: &ImportSuggestion| v.did != did) { + candidates.push(ImportSuggestion { did, descr: res.descr(), path }); + } } } } @@ -1475,7 +1477,7 @@ crate fn show_candidates( // This is `None` if all placement locations are inside expansions use_placement_span: Option, candidates: &[ImportSuggestion], - better: bool, + instead: bool, found_use: bool, ) { if candidates.is_empty() { @@ -1486,6 +1488,7 @@ crate fn show_candidates( // by iterating through a hash map, so make sure they are ordered: let mut path_strings: Vec<_> = candidates.iter().map(|c| path_names_to_string(&c.path)).collect(); + path_strings.sort(); path_strings.dedup(); @@ -1494,8 +1497,9 @@ crate fn show_candidates( } else { ("one of these", "items") }; - let instead = if better { " instead" } else { "" }; - let msg = format!("consider importing {} {}{}", determiner, kind, instead); + + let instead = if instead { " instead" } else { "" }; + let mut msg = format!("consider importing {} {}{}", determiner, kind, instead); if let Some(span) = use_placement_span { for candidate in &mut path_strings { @@ -1507,12 +1511,13 @@ crate fn show_candidates( err.span_suggestions(span, &msg, path_strings.into_iter(), Applicability::Unspecified); } else { - let mut msg = msg; msg.push(':'); + for candidate in path_strings { msg.push('\n'); msg.push_str(&candidate); } + err.note(&msg); } } diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index 3b49b3b6ff7d2..2085c8109fd5c 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -29,8 +29,9 @@ use rustc_span::Span; use smallvec::{smallvec, SmallVec}; use log::debug; +use rustc_span::source_map::{respan, Spanned}; use std::collections::BTreeSet; -use std::mem::replace; +use std::mem::{replace, take}; mod diagnostics; crate mod lifetimes; @@ -234,6 +235,13 @@ impl<'a> PathSource<'a> { } } + fn is_call(self) -> bool { + match self { + PathSource::Expr(Some(&Expr { kind: ExprKind::Call(..), .. })) => true, + _ => false, + } + } + crate fn is_expected(self, res: Res) -> bool { match self { PathSource::Type => match res { @@ -1620,14 +1628,83 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { let report_errors = |this: &mut Self, res: Option| { let (err, candidates) = this.smart_resolve_report_errors(path, span, source, res); + let def_id = this.parent_scope.module.normal_ancestor_id; - let better = res.is_some(); + let instead = res.is_some(); let suggestion = if res.is_none() { this.report_missing_type_error(path) } else { None }; - this.r.use_injections.push(UseError { err, candidates, def_id, better, suggestion }); + + this.r.use_injections.push(UseError { err, candidates, def_id, instead, suggestion }); + PartialRes::new(Res::Err) }; + // For paths originating from calls (like in `HashMap::new()`), tries + // to enrich the plain `failed to resolve: ...` message with hints + // about possible missing imports. + // + // Similar thing, for types, happens in `report_errors` above. + let report_errors_for_call = |this: &mut Self, parent_err: Spanned>| { + if !source.is_call() { + return Some(parent_err); + } + + // Before we start looking for candidates, we have to get our hands + // on the type user is trying to perform invocation on; basically: + // we're transforming `HashMap::new` into just `HashMap` + let path = if let Some((_, path)) = path.split_last() { + path + } else { + return Some(parent_err); + }; + + let (mut err, candidates) = + this.smart_resolve_report_errors(path, span, PathSource::Type, None); + + if candidates.is_empty() { + err.cancel(); + return Some(parent_err); + } + + // There are two different error messages user might receive at + // this point: + // - E0412 cannot find type `{}` in this scope + // - E0433 failed to resolve: use of undeclared type or module `{}` + // + // The first one is emitted for paths in type-position, and the + // latter one - for paths in expression-position. + // + // Thus (since we're in expression-position at this point), not to + // confuse the user, we want to keep the *message* from E0432 (so + // `parent_err`), but we want *hints* from E0412 (so `err`). + // + // And that's what happens below - we're just mixing both messages + // into a single one. + let mut parent_err = this.r.into_struct_error(parent_err.span, parent_err.node); + + parent_err.cancel(); + + err.message = take(&mut parent_err.message); + err.code = take(&mut parent_err.code); + err.children = take(&mut parent_err.children); + + drop(parent_err); + + let def_id = this.parent_scope.module.normal_ancestor_id; + + this.r.use_injections.push(UseError { + err, + candidates, + def_id, + instead: false, + suggestion: None, + }); + + // We don't return `Some(parent_err)` here, because the error will + // be already printed as part of the `use` injections + None + }; + let partial_res = match self.resolve_qpath_anywhere( id, qself, @@ -1637,14 +1714,15 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { source.defer_to_typeck(), crate_lint, ) { - Some(partial_res) if partial_res.unresolved_segments() == 0 => { + Ok(Some(partial_res)) if partial_res.unresolved_segments() == 0 => { if is_expected(partial_res.base_res()) || partial_res.base_res() == Res::Err { partial_res } else { report_errors(self, Some(partial_res.base_res())) } } - Some(partial_res) if source.defer_to_typeck() => { + + Ok(Some(partial_res)) if source.defer_to_typeck() => { // Not fully resolved associated item `T::A::B` or `::A::B` // or `::A::B`. If `B` should be resolved in value namespace then // it needs to be added to the trait map. @@ -1655,25 +1733,34 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { } let mut std_path = vec![Segment::from_ident(Ident::with_dummy_span(sym::std))]; + std_path.extend(path); + if self.r.primitive_type_table.primitive_types.contains_key(&path[0].ident.name) { - let cl = CrateLint::No; - let ns = Some(ns); if let PathResult::Module(_) | PathResult::NonModule(_) = - self.resolve_path(&std_path, ns, false, span, cl) + self.resolve_path(&std_path, Some(ns), false, span, CrateLint::No) { - // check if we wrote `str::from_utf8` instead of `std::str::from_utf8` + // Check if we wrote `str::from_utf8` instead of `std::str::from_utf8` let item_span = path.iter().last().map(|segment| segment.ident.span).unwrap_or(span); - debug!("accessed item from `std` submodule as a bare type {:?}", std_path); + let mut hm = self.r.session.confused_type_with_std_module.borrow_mut(); hm.insert(item_span, span); - // In some places (E0223) we only have access to the full path hm.insert(span, span); } } + partial_res } + + Err(err) => { + if let Some(err) = report_errors_for_call(self, err) { + self.r.report_error(err.span, err.node); + } + + PartialRes::new(Res::Err) + } + _ => report_errors(self, None), }; @@ -1682,6 +1769,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { // Avoid recording definition of `A::B` in `::B::C`. self.r.record_partial_res(id, partial_res); } + partial_res } @@ -1711,17 +1799,16 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { span: Span, defer_to_typeck: bool, crate_lint: CrateLint, - ) -> Option { + ) -> Result, Spanned>> { let mut fin_res = None; + for (i, ns) in [primary_ns, TypeNS, ValueNS].iter().cloned().enumerate() { if i == 0 || ns != primary_ns { - match self.resolve_qpath(id, qself, path, ns, span, crate_lint) { - // If defer_to_typeck, then resolution > no resolution, - // otherwise full resolution > partial resolution > no resolution. + match self.resolve_qpath(id, qself, path, ns, span, crate_lint)? { Some(partial_res) if partial_res.unresolved_segments() == 0 || defer_to_typeck => { - return Some(partial_res); + return Ok(Some(partial_res)); } partial_res => { if fin_res.is_none() { @@ -1732,19 +1819,19 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { } } - // `MacroNS` assert!(primary_ns != MacroNS); + if qself.is_none() { let path_seg = |seg: &Segment| PathSegment::from_ident(seg.ident); let path = Path { segments: path.iter().map(path_seg).collect(), span }; if let Ok((_, res)) = self.r.resolve_macro_path(&path, None, &self.parent_scope, false, false) { - return Some(PartialRes::new(res)); + return Ok(Some(PartialRes::new(res))); } } - fin_res + Ok(fin_res) } /// Handles paths that may refer to associated items. @@ -1756,7 +1843,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { ns: Namespace, span: Span, crate_lint: CrateLint, - ) -> Option { + ) -> Result, Spanned>> { debug!( "resolve_qpath(id={:?}, qself={:?}, path={:?}, ns={:?}, span={:?})", id, qself, path, ns, span, @@ -1767,10 +1854,10 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { // This is a case like `::B`, where there is no // trait to resolve. In that case, we leave the `B` // segment to be resolved by type-check. - return Some(PartialRes::with_unresolved_segments( + return Ok(Some(PartialRes::with_unresolved_segments( Res::Def(DefKind::Mod, DefId::local(CRATE_DEF_INDEX)), path.len(), - )); + ))); } // Make sure `A::B` in `::C` is a trait item. @@ -1800,10 +1887,10 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { // The remaining segments (the `C` in our example) will // have to be resolved by type-check, since that requires doing // trait resolution. - return Some(PartialRes::with_unresolved_segments( + return Ok(Some(PartialRes::with_unresolved_segments( partial_res.base_res(), partial_res.unresolved_segments() + path.len() - qself.position - 1, - )); + ))); } let result = match self.resolve_path(&path, Some(ns), true, span, crate_lint) { @@ -1838,11 +1925,10 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { PartialRes::new(module.res().unwrap()) } PathResult::Failed { is_error_from_last_segment: false, span, label, suggestion } => { - self.r.report_error(span, ResolutionError::FailedToResolve { label, suggestion }); - PartialRes::new(Res::Err) + return Err(respan(span, ResolutionError::FailedToResolve { label, suggestion })); } - PathResult::Module(..) | PathResult::Failed { .. } => return None, - PathResult::Indeterminate => bug!("indetermined path result in resolve_qpath"), + PathResult::Module(..) | PathResult::Failed { .. } => return Ok(None), + PathResult::Indeterminate => bug!("indeterminate path result in resolve_qpath"), }; if path.len() > 1 @@ -1862,7 +1948,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { PathResult::Module(ModuleOrUniformRoot::Module(module)) => { module.res().unwrap() } - _ => return Some(result), + _ => return Ok(Some(result)), } }; if result.base_res() == unqualified_result { @@ -1871,7 +1957,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { } } - Some(result) + Ok(Some(result)) } fn with_resolved_label(&mut self, label: Option