diff options
| -rw-r--r-- | mk/cfg/x86_64-unknown-openbsd.mk | 1 | ||||
| -rw-r--r-- | mk/platform.mk | 10 | ||||
| -rw-r--r-- | mk/target.mk | 2 | ||||
| -rw-r--r-- | mk/tests.mk | 7 | ||||
| -rw-r--r-- | src/doc/book/syntax-index.md | 2 | ||||
| -rw-r--r-- | src/librustc_resolve/lib.rs | 78 | ||||
| -rw-r--r-- | src/test/compile-fail/suggest-path-instead-of-mod-dot-item.rs | 60 | ||||
| -rw-r--r-- | src/test/run-make/tools.mk | 6 |
8 files changed, 139 insertions, 27 deletions
diff --git a/mk/cfg/x86_64-unknown-openbsd.mk b/mk/cfg/x86_64-unknown-openbsd.mk index 261616ecf1f..e6f28482284 100644 --- a/mk/cfg/x86_64-unknown-openbsd.mk +++ b/mk/cfg/x86_64-unknown-openbsd.mk @@ -20,3 +20,4 @@ CFG_LDPATH_x86_64-unknown-openbsd := CFG_RUN_x86_64-unknown-openbsd=$(2) CFG_RUN_TARG_x86_64-unknown-openbsd=$(call CFG_RUN_x86_64-unknown-openbsd,,$(2)) CFG_GNU_TRIPLE_x86_64-unknown-openbsd := x86_64-unknown-openbsd +RUSTC_FLAGS_x86_64-unknown-openbsd=-C linker=$(call FIND_COMPILER,$(CC)) diff --git a/mk/platform.mk b/mk/platform.mk index fd8416e8a6e..04cab379de3 100644 --- a/mk/platform.mk +++ b/mk/platform.mk @@ -215,16 +215,6 @@ define CFG_MAKE_TOOLCHAIN ifeq ($$(findstring $(HOST_$(1)),arm aarch64 mips mipsel powerpc),) - # On OpenBSD, we need to pass the path of libstdc++.so to the linker - # (use path of libstdc++.a which is a known name for the same path) - ifeq ($(OSTYPE_$(1)),unknown-openbsd) - STDCPP_LIBDIR_RUSTFLAGS_$(1)= \ - -L "$$(dir $$(shell $$(CC_$(1)) $$(CFG_GCCISH_CFLAGS_$(1)) \ - -print-file-name=lib$(CFG_STDCPP_NAME).a))" - else - STDCPP_LIBDIR_RUSTFLAGS_$(1)= - endif - # On Bitrig, we need the relocation model to be PIC for everything ifeq (,$(filter $(OSTYPE_$(1)),bitrig)) LLVM_MC_RELOCATION_MODEL="pic" diff --git a/mk/target.mk b/mk/target.mk index 9d5e633c3c6..f90b09479c9 100644 --- a/mk/target.mk +++ b/mk/target.mk @@ -95,7 +95,6 @@ $$(TLIB$(1)_T_$(2)_H_$(3))/stamp.$(4): \ $$(RUSTFLAGS_$(4)) \ $$(RUSTFLAGS$(1)_$(4)) \ $$(RUSTFLAGS$(1)_$(4)_T_$(2)) \ - $$(STDCPP_LIBDIR_RUSTFLAGS_$(2)) \ --out-dir $$(@D) \ -C extra-filename=-$$(CFG_FILENAME_EXTRA) \ $$< @@ -130,7 +129,6 @@ $$(TBIN$(1)_T_$(2)_H_$(3))/$(4)$$(X_$(2)): \ | $$(TBIN$(1)_T_$(2)_H_$(3))/ @$$(call E, rustc: $$@) $$(STAGE$(1)_T_$(2)_H_$(3)) \ - $$(STDCPP_LIBDIR_RUSTFLAGS_$(2)) \ $$(LLVM_LIBDIR_RUSTFLAGS_$(2)) \ -o $$@ $$< --cfg $(4) diff --git a/mk/tests.mk b/mk/tests.mk index bd7414a3bb6..0f30ff8711e 100644 --- a/mk/tests.mk +++ b/mk/tests.mk @@ -393,8 +393,7 @@ $(3)/stage$(1)/test/$(4)test-$(2)$$(X_$(2)): \ $$(subst @,,$$(STAGE$(1)_T_$(2)_H_$(3))) -o $$@ $$< --test \ -L "$$(RT_OUTPUT_DIR_$(2))" \ $$(LLVM_LIBDIR_RUSTFLAGS_$(2)) \ - $$(RUSTFLAGS_$(4)) \ - $$(STDCPP_LIBDIR_RUSTFLAGS_$(2)) + $$(RUSTFLAGS_$(4)) endef @@ -664,9 +663,9 @@ CTEST_COMMON_ARGS$(1)-T-$(2)-H-$(3) := \ --android-cross-path=$(CFG_ANDROID_CROSS_PATH) \ --adb-path=$(CFG_ADB) \ --adb-test-dir=$(CFG_ADB_TEST_DIR) \ - --host-rustcflags "$(RUSTC_FLAGS_$(3)) $$(CTEST_RUSTC_FLAGS) -L $$(RT_OUTPUT_DIR_$(3)) $$(STDCPP_LIBDIR_RUSTFLAGS_$(3))" \ + --host-rustcflags "$(RUSTC_FLAGS_$(3)) $$(CTEST_RUSTC_FLAGS) -L $$(RT_OUTPUT_DIR_$(3))" \ --lldb-python-dir=$(CFG_LLDB_PYTHON_DIR) \ - --target-rustcflags "$(RUSTC_FLAGS_$(2)) $$(CTEST_RUSTC_FLAGS) -L $$(RT_OUTPUT_DIR_$(2)) $$(STDCPP_LIBDIR_RUSTFLAGS_$(2))" \ + --target-rustcflags "$(RUSTC_FLAGS_$(2)) $$(CTEST_RUSTC_FLAGS) -L $$(RT_OUTPUT_DIR_$(2))" \ $$(CTEST_TESTARGS) ifdef CFG_VALGRIND_RPASS diff --git a/src/doc/book/syntax-index.md b/src/doc/book/syntax-index.md index 528c0b537f3..01f06f718f8 100644 --- a/src/doc/book/syntax-index.md +++ b/src/doc/book/syntax-index.md @@ -234,5 +234,5 @@ [Traits (Multiple Trait Bounds)]: traits.html#multiple-trait-bounds [Traits]: traits.html [Unsafe]: unsafe.html -[Unsized Types (`?Sized`)]: unsized-types.html#?sized +[Unsized Types (`?Sized`)]: unsized-types.html#sized [Variable Bindings]: variable-bindings.html diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 6896e8e5340..3f7327e700b 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -179,7 +179,7 @@ pub enum ResolutionError<'a> { /// error E0424: `self` is not available in a static method SelfNotAvailableInStaticMethod, /// error E0425: unresolved name - UnresolvedName(&'a str, &'a str), + UnresolvedName(&'a str, &'a str, UnresolvedNameContext), /// error E0426: use of undeclared label UndeclaredLabel(&'a str), /// error E0427: cannot use `ref` binding mode with ... @@ -202,6 +202,21 @@ pub enum ResolutionError<'a> { AttemptToUseNonConstantValueInConstant, } +/// Context of where `ResolutionError::UnresolvedName` arose. +#[derive(Clone, PartialEq, Eq, Debug)] +pub enum UnresolvedNameContext { + /// `PathIsMod(id)` indicates that a given path, used in + /// expression context, actually resolved to a module rather than + /// a value. The `id` attached to the variant is the node id of + /// the erroneous path expression. + PathIsMod(ast::NodeId), + + /// `Other` means we have no extra information about the context + /// of the unresolved name error. (Maybe we could eliminate all + /// such cases; but for now, this is an information-free default.) + Other, +} + fn resolve_error<'b, 'a: 'b, 'tcx: 'a>(resolver: &'b Resolver<'a, 'tcx>, span: syntax::codemap::Span, resolution_error: ResolutionError<'b>) { @@ -402,13 +417,46 @@ fn resolve_error<'b, 'a: 'b, 'tcx: 'a>(resolver: &'b Resolver<'a, 'tcx>, "`self` is not available in a static method. Maybe a `self` argument is \ missing?"); } - ResolutionError::UnresolvedName(path, name) => { + ResolutionError::UnresolvedName(path, msg, context) => { span_err!(resolver.session, span, E0425, "unresolved name `{}`{}", path, - name); + msg); + + match context { + UnresolvedNameContext::Other => {} // no help available + UnresolvedNameContext::PathIsMod(id) => { + let mut help_msg = String::new(); + let parent_id = resolver.ast_map.get_parent_node(id); + if let Some(hir_map::Node::NodeExpr(e)) = resolver.ast_map.find(parent_id) { + match e.node { + ExprField(_, ident) => { + help_msg = format!("To reference an item from the \ + `{module}` module, use \ + `{module}::{ident}`", + module = &*path, + ident = ident.node); + } + + ExprMethodCall(ident, _, _) => { + help_msg = format!("To call a function from the \ + `{module}` module, use \ + `{module}::{ident}(..)`", + module = &*path, + ident = ident.node); + } + + _ => {} // no help available + } + } + + if !help_msg.is_empty() { + resolver.session.fileline_help(span, &help_msg); + } + } + } } ResolutionError::UndeclaredLabel(name) => { span_err!(resolver.session, @@ -3539,13 +3587,33 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { format!("to call `{}::{}`", path_str, path_name), }; + let mut context = UnresolvedNameContext::Other; if !msg.is_empty() { - msg = format!(". Did you mean {}?", msg) + msg = format!(". Did you mean {}?", msg); + } else { + // we check if this a module and if so, we display a help + // message + let name_path = path.segments.iter() + .map(|seg| seg.identifier.name) + .collect::<Vec<_>>(); + let current_module = self.current_module.clone(); + + match self.resolve_module_path(current_module, + &name_path[..], + UseLexicalScope, + expr.span, + PathSearch) { + Success(_) => { + context = UnresolvedNameContext::PathIsMod(expr.id); + }, + _ => {}, + }; } resolve_error(self, expr.span, - ResolutionError::UnresolvedName(&*path_name, &*msg)); + ResolutionError::UnresolvedName( + &*path_name, &*msg, context)); } } } diff --git a/src/test/compile-fail/suggest-path-instead-of-mod-dot-item.rs b/src/test/compile-fail/suggest-path-instead-of-mod-dot-item.rs new file mode 100644 index 00000000000..ecf17fa84d7 --- /dev/null +++ b/src/test/compile-fail/suggest-path-instead-of-mod-dot-item.rs @@ -0,0 +1,60 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Beginners write `mod.item` when they should write `mod::item`. +// This tests that we suggest the latter when we encounter the former. + +pub mod a { + pub const I: i32 = 1; + + pub fn f() -> i32 { 2 } + + pub mod b { + pub const J: i32 = 3; + + pub fn g() -> i32 { 4 } + } +} + +fn h1() -> i32 { + a.I + //~^ ERROR E0425 + //~| HELP To reference an item from the `a` module, use `a::I` +} + +fn h2() -> i32 { + a.g() + //~^ ERROR E0425 + //~| HELP To call a function from the `a` module, use `a::g(..)` +} + +fn h3() -> i32 { + a.b.J + //~^ ERROR E0425 + //~| HELP To reference an item from the `a` module, use `a::b` +} + +fn h4() -> i32 { + a::b.J + //~^ ERROR E0425 + //~| HELP To reference an item from the `a::b` module, use `a::b::J` +} + +fn h5() -> i32 { + a.b.f() + //~^ ERROR E0425 + //~| HELP To reference an item from the `a` module, use `a::b` +} + +fn h6() -> i32 { + a::b.f() + //~^ ERROR E0425 + //~| HELP To call a function from the `a::b` module, use `a::b::f(..)` +} diff --git a/src/test/run-make/tools.mk b/src/test/run-make/tools.mk index 88cf2a2b031..efaf1197fbd 100644 --- a/src/test/run-make/tools.mk +++ b/src/test/run-make/tools.mk @@ -85,11 +85,7 @@ ifeq ($(UNAME),Bitrig) else ifeq ($(UNAME),OpenBSD) EXTRACFLAGS := -lm -lpthread - # extend search lib for found estdc++ if build using gcc from - # ports under OpenBSD. This is needed for: - # - run-make/execution-engine - # - run-make/issue-19371 - RUSTC := $(RUSTC) -L/usr/local/lib + RUSTC := $(RUSTC) -C linker="$(word 1,$(CC:ccache=))" else EXTRACFLAGS := -lm -lrt -ldl -lpthread EXTRACXXFLAGS := -lstdc++ |
