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, //< 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() { ... } +} + impl NameBindings { /// Creates a new module in this set of name bindings. pub fn define_module(@mut self, @@ -3554,23 +3561,7 @@ pub fn resolve_item(@mut self, item: @item, visitor: ResolveVisitor) { // 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 @@ pub fn resolve_type_parameter_bound(@mut self, 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 @@ pub fn resolve_type_parameter_bound(@mut self, 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 @@ pub fn resolve_implementation(@mut self, 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 or the MIT license +// , 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() {} +//~^ ERROR attempt to bound type parameter to a nonexistent trait `SomeNonExistentTrait` +