Skip to content

Commit e08a6c2

Browse files
authored
Auto merge of #34797 - doomrobo:fix-import-trait-method, r=jseyfried
Fixed issue where importing a trait method directly and then calling the method causes a compiler panic The code below triggers the panic, and is included in a new regression test. ```rust trait Foo { fn foo(); } use Foo::foo; fn main() { foo(); } ``` The bug is caused by `librustc_resolve` allowing the illegal binding to be imported even after displaying the error message above. The fix amounts to importing a dummy binding (`rustc::hir::def::Def::Err`) instead of the actual trait method.
2 parents 78d49bf + 5a99d79 commit e08a6c2

File tree

2 files changed

+35
-10
lines changed

2 files changed

+35
-10
lines changed

src/librustc_resolve/resolve_imports.rs

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -400,26 +400,30 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
400400
}
401401
}
402402

403-
/// Resolves an `ImportResolvingError` into the correct enum discriminant
404-
/// and passes that on to `resolve_error`.
405-
fn import_resolving_error(&self, e: ImportResolvingError<'b>) {
406-
// If it's a single failed import then create a "fake" import
407-
// resolution for it so that later resolve stages won't complain.
408-
if let SingleImport { target, .. } = e.import_directive.subclass {
403+
// Define a "dummy" resolution containing a Def::Err as a placeholder for a
404+
// failed resolution
405+
fn import_dummy_binding(&self, source_module: Module<'b>, directive: &'b ImportDirective<'b>) {
406+
if let SingleImport { target, .. } = directive.subclass {
409407
let dummy_binding = self.resolver.arenas.alloc_name_binding(NameBinding {
410408
kind: NameBindingKind::Def(Def::Err),
411409
span: DUMMY_SP,
412410
vis: ty::Visibility::Public,
413411
});
414-
let dummy_binding = e.import_directive.import(dummy_binding, None);
412+
let dummy_binding = directive.import(dummy_binding, None);
415413

416-
let _ = e.source_module.try_define_child(target, ValueNS, dummy_binding.clone());
417-
let _ = e.source_module.try_define_child(target, TypeNS, dummy_binding);
414+
let _ = source_module.try_define_child(target, ValueNS, dummy_binding.clone());
415+
let _ = source_module.try_define_child(target, TypeNS, dummy_binding);
418416
}
417+
}
419418

419+
/// Resolves an `ImportResolvingError` into the correct enum discriminant
420+
/// and passes that on to `resolve_error`.
421+
fn import_resolving_error(&self, e: ImportResolvingError<'b>) {
422+
// If the error is a single failed import then create a "fake" import
423+
// resolution for it so that later resolve stages won't complain.
424+
self.import_dummy_binding(e.source_module, e.import_directive);
420425
let path = import_path_to_string(&e.import_directive.module_path,
421426
&e.import_directive.subclass);
422-
423427
resolve_error(self.resolver,
424428
e.span,
425429
ResolutionError::UnresolvedImport(Some((&path, &e.help))));
@@ -500,6 +504,10 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
500504
if !binding.is_importable() {
501505
let msg = format!("`{}` is not directly importable", target);
502506
span_err!(self.resolver.session, directive.span, E0253, "{}", &msg);
507+
// Do not import this illegal binding. Import a dummy binding and pretend
508+
// everything is fine
509+
self.import_dummy_binding(module_, directive);
510+
return Success(());
503511
}
504512

505513
let privacy_error = if !self.resolver.is_accessible(binding.vis) {
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
trait Foo {
12+
fn foo();
13+
}
14+
15+
use Foo::foo; //~ ERROR not directly importable
16+
17+
fn main() { foo(); }

0 commit comments

Comments
 (0)