about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGareth Smith <garethdanielsmith@gmail.com>2013-07-03 22:16:08 +0100
committerGareth Smith <garethdanielsmith@gmail.com>2013-07-03 22:16:08 +0100
commit656c8f91435df99b11bfe31be73eba6d8f391870 (patch)
treeedaa7084f70a140e25c40bc5d018b6fa2aa2bbfe
parent0c6fc46c030ab0515a052fa99c9e10c75cfc8184 (diff)
downloadrust-656c8f91435df99b11bfe31be73eba6d8f391870.tar.gz
rust-656c8f91435df99b11bfe31be73eba6d8f391870.zip
Make the error messages that result from referencing
nonexistent traits consistent, and add a test.
-rw-r--r--src/librustc/middle/resolve.rs46
-rw-r--r--src/test/compile-fail/resolve-unknown-trait.rs20
2 files changed, 43 insertions, 23 deletions
diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs
index 8e25f598f36..6ddac371e0c 100644
--- a/src/librustc/middle/resolve.rs
+++ b/src/librustc/middle/resolve.rs
@@ -510,6 +510,13 @@ pub struct NameBindings {
     value_def: Option<ValueNsDef>,  //< Meaning in value namespace.
 }
 
+/// Ways in which a trait can be referenced
+enum TraitReferenceType {
+    TraitImplementation,             // impl SomeTrait for T { ... }
+    TraitDerivation,                 // trait T : SomeTrait { ... }
+    TraitBoundingTypeParameter,      // fn f<T:SomeTrait>() { ... }
+}
+
 impl NameBindings {
     /// Creates a new module in this set of name bindings.
     pub fn define_module(@mut self,
@@ -3554,23 +3561,7 @@ impl Resolver {
 
                     // Resolve derived traits.
                     for traits.iter().advance |trt| {
-                        match self.resolve_path(trt.path, TypeNS, true,
-                                                visitor) {
-                            None =>
-                                self.session.span_err(trt.path.span,
-                                                      "attempt to derive a \
-                                                      nonexistent trait"),
-                            Some(def) => {
-                                // Write a mapping from the trait ID to the
-                                // definition of the trait into the definition
-                                // map.
-
-                                debug!("(resolving trait) found trait def: \
-                                       %?", def);
-
-                                self.record_def(trt.ref_id, def);
-                            }
-                        }
+                        self.resolve_trait_reference(*trt, visitor, TraitDerivation);
                     }
 
                     for (*methods).iter().advance |method| {
@@ -3821,7 +3812,7 @@ impl Resolver {
                                         visitor: ResolveVisitor) {
         match *type_parameter_bound {
             TraitTyParamBound(tref) => {
-                self.resolve_trait_reference(tref, visitor)
+                self.resolve_trait_reference(tref, visitor, TraitBoundingTypeParameter)
             }
             RegionTyParamBound => {}
         }
@@ -3829,14 +3820,23 @@ impl Resolver {
 
     pub fn resolve_trait_reference(@mut self,
                                    trait_reference: &trait_ref,
-                                   visitor: ResolveVisitor) {
+                                   visitor: ResolveVisitor,
+                                   reference_type: TraitReferenceType) {
         match self.resolve_path(trait_reference.path, TypeNS, true, visitor) {
             None => {
-                let idents = self.idents_to_str(trait_reference.path.idents);
-                self.session.span_err(trait_reference.path.span,
-                                      fmt!("attempt to implement an unknown trait `%s`", idents));
+                let path_str = self.idents_to_str(trait_reference.path.idents);
+
+                let usage_str = match reference_type {
+                    TraitBoundingTypeParameter => "bound type parameter to",
+                    TraitImplementation        => "implement",
+                    TraitDerivation            => "derive"
+                };
+
+                let msg = fmt!("attempt to %s a nonexistent trait `%s`", usage_str, path_str);
+                self.session.span_err(trait_reference.path.span, msg);
             }
             Some(def) => {
+                debug!("(resolving trait) found trait def: %?", def);
                 self.record_def(trait_reference.ref_id, def);
             }
         }
@@ -3930,7 +3930,7 @@ impl Resolver {
             let original_trait_refs;
             match opt_trait_reference {
                 Some(trait_reference) => {
-                    self.resolve_trait_reference(trait_reference, visitor);
+                    self.resolve_trait_reference(trait_reference, visitor, TraitImplementation);
 
                     // Record the current set of trait references.
                     let mut new_trait_refs = ~[];
diff --git a/src/test/compile-fail/resolve-unknown-trait.rs b/src/test/compile-fail/resolve-unknown-trait.rs
new file mode 100644
index 00000000000..be3b381663a
--- /dev/null
+++ b/src/test/compile-fail/resolve-unknown-trait.rs
@@ -0,0 +1,20 @@
+// Copyright 2013 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.
+
+
+trait NewTrait : SomeNonExistentTrait {}
+//~^ ERROR attempt to derive a nonexistent trait `SomeNonExistentTrait`
+
+impl SomeNonExistentTrait for int {}
+//~^ ERROR attempt to implement a nonexistent trait `SomeNonExistentTrait`
+
+fn f<T:SomeNonExistentTrait>() {}
+//~^ ERROR attempt to bound type parameter to a nonexistent trait `SomeNonExistentTrait`
+