-
Notifications
You must be signed in to change notification settings - Fork 13.4k
resolve: Improve duplicate glob detection #32814
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -275,7 +275,6 @@ impl<'a> ::ModuleS<'a> { | |
// Define the name or return the existing binding if there is a collision. | ||
pub fn try_define_child(&self, name: Name, ns: Namespace, binding: NameBinding<'a>) | ||
-> Result<(), &'a NameBinding<'a>> { | ||
if self.resolutions.borrow_state() != ::std::cell::BorrowState::Unused { return Ok(()); } | ||
self.update_resolution(name, ns, |resolution| { | ||
resolution.try_define(self.arenas.alloc_name_binding(binding)) | ||
}) | ||
|
@@ -318,15 +317,22 @@ impl<'a> ::ModuleS<'a> { | |
fn update_resolution<T, F>(&self, name: Name, ns: Namespace, update: F) -> T | ||
where F: FnOnce(&mut NameResolution<'a>) -> T | ||
{ | ||
let mut resolution = &mut *self.resolution(name, ns).borrow_mut(); | ||
let was_known = resolution.binding().is_some(); | ||
|
||
let t = update(resolution); | ||
if !was_known { | ||
if let Some(binding) = resolution.binding() { | ||
self.define_in_glob_importers(name, ns, binding); | ||
// Ensure that `resolution` isn't borrowed during `define_in_glob_importers`, | ||
// where it might end up getting re-defined via a glob cycle. | ||
let (new_binding, t) = { | ||
let mut resolution = &mut *self.resolution(name, ns).borrow_mut(); | ||
let was_known = resolution.binding().is_some(); | ||
|
||
let t = update(resolution); | ||
|
||
if was_known { return t; } | ||
match resolution.binding() { | ||
Some(binding) => (binding, t), | ||
None => return t, | ||
} | ||
} | ||
}; | ||
|
||
self.define_in_glob_importers(name, ns, new_binding); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The above change is so that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I'd suggest adding this as a comment into the code :) (also the note you added below) |
||
t | ||
} | ||
|
||
|
@@ -646,11 +652,14 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { | |
// Add to target_module's glob_importers | ||
target_module.glob_importers.borrow_mut().push((module_, directive)); | ||
|
||
for (&(name, ns), resolution) in target_module.resolutions.borrow().iter() { | ||
if let Some(binding) = resolution.borrow().binding() { | ||
if binding.defined_with(DefModifiers::IMPORTABLE | DefModifiers::PUBLIC) { | ||
let _ = module_.try_define_child(name, ns, directive.import(binding, None)); | ||
} | ||
// Ensure that `resolutions` isn't borrowed during `try_define_child`, | ||
// since it might get updated via a glob cycle. | ||
let bindings = target_module.resolutions.borrow().iter().filter_map(|(name, resolution)| { | ||
resolution.borrow().binding().map(|binding| (*name, binding)) | ||
}).collect::<Vec<_>>(); | ||
for ((name, ns), binding) in bindings { | ||
if binding.defined_with(DefModifiers::IMPORTABLE | DefModifiers::PUBLIC) { | ||
let _ = module_.try_define_child(name, ns, directive.import(binding, None)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
} | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
// Copyright 2016 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. | ||
|
||
mod foo { | ||
pub use bar::*; | ||
pub use main as f; //~ ERROR has already been imported | ||
} | ||
|
||
mod bar { | ||
pub use foo::*; | ||
} | ||
|
||
pub use foo::*; | ||
pub use baz::*; //~ ERROR has already been imported | ||
mod baz { | ||
pub use super::*; | ||
} | ||
|
||
pub fn main() {} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
// Copyright 2016 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. | ||
|
||
pub use bar::*; | ||
mod bar { | ||
pub use super::*; | ||
} | ||
|
||
pub use baz::*; //~ ERROR already been imported | ||
mod baz { | ||
pub use main as f; | ||
} | ||
|
||
pub fn main() {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line was preventing the duplicate errors from being reported.