diff options
| author | bors <bors@rust-lang.org> | 2014-12-14 09:22:24 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2014-12-14 09:22:24 +0000 |
| commit | 3a9305ce823df267fb1afcce76ef06ca09e407ff (patch) | |
| tree | 75b3af504a1218014bec477c86bd2910899b5b33 /src | |
| parent | 10ac5b72f1974775bed499105c2a3cf18da98f32 (diff) | |
| parent | cfee5b7e881d6cfd65557ca98aff043d9b8fea49 (diff) | |
| download | rust-3a9305ce823df267fb1afcce76ef06ca09e407ff.tar.gz rust-3a9305ce823df267fb1afcce76ef06ca09e407ff.zip | |
auto merge of #19690 : barosl/rust/struct-variant-as-a-function-ice, r=alexcrichton
Unlike a tuple variant constructor which can be called as a function, a struct variant constructor is not a function, so cannot be called. If the user tries to assign the constructor to a variable, an ICE occurs, because there is no way to use it later. So we should stop the constructor from being used like that. A similar mechanism already exists for a normal struct, as it prohibits a struct from being resolved. This commit does the same for a struct variant. This commit also includes some changes to the existing tests. Fixes #19452.
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustc/middle/resolve.rs | 34 | ||||
| -rw-r--r-- | src/test/compile-fail/issue-18252.rs | 2 | ||||
| -rw-r--r-- | src/test/compile-fail/issue-19452.rs | 17 |
3 files changed, 42 insertions, 11 deletions
diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index 85e0c9294a6..bec3fa77b07 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -5807,16 +5807,30 @@ impl<'a> Resolver<'a> { // This is a local path in the value namespace. Walk through // scopes looking for it. + let path_name = self.path_names_to_string(path); + match self.resolve_path(expr.id, path, ValueNS, true) { + // Check if struct variant + Some((DefVariant(_, _, true), _)) => { + self.resolve_error(expr.span, + format!("`{}` is a struct variant name, but \ + this expression \ + uses it like a function name", + path_name).as_slice()); + + self.session.span_help(expr.span, + format!("Did you mean to write: \ + `{} {{ /* fields */ }}`?", + path_name).as_slice()); + } Some(def) => { // Write the result into the def map. debug!("(resolving expr) resolved `{}`", - self.path_names_to_string(path)); + path_name); self.record_def(expr.id, def); } None => { - let wrong_name = self.path_names_to_string(path); // Be helpful if the name refers to a struct // (The pattern matching def_tys where the id is in self.structs // matches on regular structs while excluding tuple- and enum-like @@ -5829,12 +5843,12 @@ impl<'a> Resolver<'a> { format!("`{}` is a structure name, but \ this expression \ uses it like a function name", - wrong_name).as_slice()); + path_name).as_slice()); self.session.span_help(expr.span, format!("Did you mean to write: \ `{} {{ /* fields */ }}`?", - wrong_name).as_slice()); + path_name).as_slice()); } _ => { @@ -5851,7 +5865,7 @@ impl<'a> Resolver<'a> { }); if method_scope && token::get_name(self.self_name).get() - == wrong_name { + == path_name { self.resolve_error( expr.span, "`self` is not available \ @@ -5863,18 +5877,18 @@ impl<'a> Resolver<'a> { NoSuggestion => { // limit search to 5 to reduce the number // of stupid suggestions - self.find_best_match_for_name(wrong_name.as_slice(), 5) + self.find_best_match_for_name(path_name.as_slice(), 5) .map_or("".to_string(), |x| format!("`{}`", x)) } Field => - format!("`self.{}`", wrong_name), + format!("`self.{}`", path_name), Method | TraitItem => - format!("to call `self.{}`", wrong_name), + format!("to call `self.{}`", path_name), TraitMethod(path_str) | StaticMethod(path_str) => - format!("to call `{}::{}`", path_str, wrong_name) + format!("to call `{}::{}`", path_str, path_name) }; if msg.len() > 0 { @@ -5884,7 +5898,7 @@ impl<'a> Resolver<'a> { self.resolve_error( expr.span, format!("unresolved name `{}`{}", - wrong_name, + path_name, msg).as_slice()); } } diff --git a/src/test/compile-fail/issue-18252.rs b/src/test/compile-fail/issue-18252.rs index a655d61fa56..02493b96dc8 100644 --- a/src/test/compile-fail/issue-18252.rs +++ b/src/test/compile-fail/issue-18252.rs @@ -13,5 +13,5 @@ enum Foo { } fn main() { - let f = Foo::Variant(42u); //~ ERROR expected function, found `Foo` + let f = Foo::Variant(42u); //~ ERROR uses it like a function } diff --git a/src/test/compile-fail/issue-19452.rs b/src/test/compile-fail/issue-19452.rs new file mode 100644 index 00000000000..2270ba594ad --- /dev/null +++ b/src/test/compile-fail/issue-19452.rs @@ -0,0 +1,17 @@ +// Copyright 2014 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. + +enum Homura { + Madoka { age: u32 } +} + +fn main() { + let homura = Homura::Madoka; //~ ERROR uses it like a function +} |
