From 48fbbee67c517bfe6159e7daf7232c830e476829 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 13 Oct 2019 01:46:04 +0300 Subject: [PATCH 1/2] resolve: Make traits to always be in scope for associated item resolution Ignoring macro 2.0 hygiene. --- src/librustc_resolve/late.rs | 36 ++++++++++-------------------------- 1 file changed, 10 insertions(+), 26 deletions(-) diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index bb9f895c5f39b..47d9cf049d04b 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -2038,35 +2038,19 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { } for &(trait_name, binding) in traits.as_ref().unwrap().iter() { - // Traits have pseudo-modules that can be used to search for the given ident. - if let Some(module) = binding.module() { - let mut ident = ident; - if ident.span.glob_adjust( - module.expansion, - binding.span, - ).is_none() { - continue - } - if self.r.resolve_ident_in_module_unadjusted( - ModuleOrUniformRoot::Module(module), - ident, - ns, - &self.parent_scope, - false, - module.span, - ).is_ok() { - let import_ids = self.find_transitive_imports(&binding.kind, trait_name); - let trait_def_id = module.def_id().unwrap(); - found_traits.push(TraitCandidate { def_id: trait_def_id, import_ids }); - } - } else if let Res::Def(DefKind::TraitAlias, _) = binding.res() { - // For now, just treat all trait aliases as possible candidates, since we don't - // know if the ident is somewhere in the transitive bounds. + // Prune the trait list on best effort basis. We reject traits not having associated + // items with the necessary name and namespace. We don't reject trait aliases because + // we don't have access to their associted items. + let is_candidate = binding.module().map_or(true, |trait_module| { + self.r.resolutions(trait_module).borrow().iter().any(|resolution| { + let (&(assoc_ident, assoc_ns), _) = resolution; + assoc_ns == ns && assoc_ident.name == ident.name + }) + }); + if is_candidate { let import_ids = self.find_transitive_imports(&binding.kind, trait_name); let trait_def_id = binding.res().def_id(); found_traits.push(TraitCandidate { def_id: trait_def_id, import_ids }); - } else { - bug!("candidate is not trait or trait alias?") } } } From 745b2390b25704530a1090ed5834728a041287b5 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 13 Oct 2019 01:52:49 +0300 Subject: [PATCH 2/2] Add a test demonstrating unhygienic behavior of traits in scope --- src/test/ui/hygiene/traits-in-scope-fixme.rs | 29 ++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 src/test/ui/hygiene/traits-in-scope-fixme.rs diff --git a/src/test/ui/hygiene/traits-in-scope-fixme.rs b/src/test/ui/hygiene/traits-in-scope-fixme.rs new file mode 100644 index 0000000000000..7f26ce3752d0b --- /dev/null +++ b/src/test/ui/hygiene/traits-in-scope-fixme.rs @@ -0,0 +1,29 @@ +// check-pass + +#![feature(decl_macro)] + +mod single { + pub trait Single { + fn single(&self) {} + } + + impl Single for u8 {} +} +mod glob { + pub trait Glob { + fn glob(&self) {} + } + + impl Glob for u8 {} +} + +macro gen_imports() { + use single::Single; + use glob::*; +} +gen_imports!(); + +fn main() { + 0u8.single(); // FIXME, should be an error, `Single` shouldn't be in scope here + 0u8.glob(); // FIXME, should be an error, `Glob` shouldn't be in scope here +}